MyBatis HelloWorld


☃ 数据库准备

create table tb_student  
(  
    Sno varchar(20),  
    Sname varchar(50),    
    primary key (Sno)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  
create table tb_course  
(  
    Cno varchar(20),  
    Cname varchar(50),    
    Tno varchar(20),  
    primary key (Cno)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  
create table tb_sc  
(  
    Sno varchar(20),  
    Cno varchar(20),      
    tb_score int,  
    primary key (Sno,Cno)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  
create table tb_teacher  
(  
    Tno varchar(20),  
    Tname varchar(50),    
    primary key (Tno)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  
INSERT INTO `tb_student`(Sno,Sname) VALUES ('001','陈一');  
INSERT INTO `tb_student`(Sno,Sname) VALUES ('002','郭二');  
INSERT INTO `tb_student`(Sno,Sname) VALUES ('003','张三');  
INSERT INTO `tb_student`(Sno,Sname) VALUES ('004','李四');  
INSERT INTO `tb_student`(Sno,Sname) VALUES ('005','王五');  
  
INSERT INTO `tb_teacher`(Tno,Tname) VALUES ('001','张老师');  
INSERT INTO `tb_teacher`(Tno,Tname) VALUES ('002','王老师');  
INSERT INTO `tb_teacher`(Tno,Tname) VALUES ('003','钱老师');  
INSERT INTO `tb_teacher`(Tno,Tname) VALUES ('004','刘老师');  
INSERT INTO `tb_teacher`(Tno,Tname) VALUES ('005','胡老师');  
  
INSERT INTO `tb_course`(Cno,Cname,Tno) VALUES ('001','语文','张老师');  
INSERT INTO `tb_course`(Cno,Cname,Tno) VALUES ('002','数学','王老师');  
INSERT INTO `tb_course`(Cno,Cname,Tno) VALUES ('003','英语','钱老师');  
INSERT INTO `tb_course`(Cno,Cname,Tno) VALUES ('004','物理','刘老师');  
INSERT INTO `tb_course`(Cno,Cname,Tno) VALUES ('005','政治','胡老师');  
  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('001','001',50);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('001','002',60);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('001','003',70);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('001','004',80);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('001','005',90);  
  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('002','001',90);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('002','002',80);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('002','003',70);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('002','004',60);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('002','005',50);  
  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('003','001',81);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('003','002',82);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('003','003',83);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('003','004',84);  
INSERT INTO `tb_sc`(Sno,Cno,tb_score) VALUES ('003','005',85); 

JDBC方式

  • 1.创建maven工程
  • 2.引入mysql驱动依赖
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>
  • 3.准备数据库数据
  • 4.JdbcTest.class
public static void main(String[] args) throws Exception {
    Connection connection = null;
    PreparedStatement prepareStatement = null;
    ResultSet rs = null;
    try {
        // 1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.获取连接
        String url = "jdbc:mysql://localhost:3306/test_mybatis?useSSL=false";
        String user = "root";
        String password = "root";
        connection = DriverManager.getConnection(url, user, password);
        // 3.获取statement||preparedStatement
        String sql = "select * from tb_student where sno=?";
        prepareStatement = connection.prepareStatement(sql);
        // 4.设置参数
        prepareStatement.setLong(1, "001");     //从1开始不是0
        // 5.执行查询
        rs = prepareStatement.executeQuery();
        // 6.处理结果集
        while (rs.next()) {
            System.out.println(rs.getString("sno"));
            System.out.println(rs.getString("sname"));
        }
    } finally {
        // 7.关闭连接,释放资源
        if (rs != null) {
            rs.close();
        }
        if (prepareStatement != null) {
            prepareStatement.close();
        }
        if (connection != null) {
            connection.close();
        }
    }
}
  • ☃ JDBC缺点
    1.四大金刚硬编码;SQL与代码耦合
    2.每次都要加载驱动,获得/关闭connection/statement/resultSet
    3.传参需要判断参数类型和下标,结果集获得结果需要判断类型和下标/列名

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

MyBatis

  • MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
  • Object relational mapping
  • 对JDBC的简单封装:JDBC > MyBatis > Hibernate
  • 官方文档
    [英文]http://www.mybatis.org/mybatis-3/index.html
    [中文]http://www.mybatis.org/mybatis-3/zh/index.html
🍀 MyBaits整体架构
image.png
A.根据创建SqlSessionFactory的方式,分成xml和annotation两种方式:
   1.xml方式需要mybatis-cofig.xml和xxMapper.xml(映射文件也可以用注解代替,但复杂SQL仍需在xxMapper.xml中书写)
   2.注解方式要全注解,读不到mybatis-cofig.xml和xxxMapper.xml???(待确认)
B.创建SqlSessionFactory和SqlSession后,根据[接口方法-Statement]的映射方式,又可分成一般和动态代理两种方式:
   1.一般方式容易出现字符串(namespace.statementId)拼写错误
   2.动态代理方式推荐使用,但须遵循4个约定
🍀 HelloWorld(3版)
①HelloWorld(最简xml版)
  • ☞ 引入依赖(pom.xml)
<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- mybatis支持了slf4j日志系统 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>
  • ☞ log4j.properties和jdbc.properties
log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_mybatis?useSSL=false
username=root
password=root
  • ☞ 全局配置文件(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 读取jdbc四大金刚 -->
    <properties resource="jdbc.properties"></properties>
    
    <!-- 环境配置 -->
    <environments default="development">
      <environment id="development">
        <!-- 事务管理 -->
        <transactionManager type="JDBC"/>
        <!-- 数据源 -->
        <dataSource type="POOLED">
          <property name="driver" value="${driver}"/>
          <property name="url" value="${url}"/>
          <property name="username" value="${username}"/>
          <property name="password" value="${password}"/>
        </dataSource>
      </environment>
    </environments>
    
    <!-- 映射文件 -->
    <mappers>
      <mapper resource="StudentMapper.xml"/>
    </mappers> 
</configuration>
  • ☞ POJO和Mapper.xml
public class Student {
    private String sno;
    private String sname;
    public String getSno() {
        return sno;
    }
    public void setSno(String sno) {
        this.sno = sno;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    @Override
    public String toString() {
        return "Student [sno=" + sno + ", sname=" + sname + "]";
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="123">
    <select id="selectById" resultType="com.top.test.pojo.Student">
        select * from tb_student where sno = #{sno}
    </select>
</mapper>
  • ☞ 测试类
public class MybatisTest {
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        try {
            Student student = sqlSession.selectOne("123.selectById", "001");
            System.out.println(student);
        } finally {
            sqlSession.close();
        }
    }
}

如果这里用SqlSession sqlSession = sqlSessionFactory.openSession(true);(重载方法,会自动提交),那么做增删改时不用手动提交了:this.sqlSession.commit();

注:简单版的helloworld没有写Mapper接口和实现类

  • ☞ 输出
2017-09-26 12:10:34,623 [main] [org.apache.ibatis.logging.LogFactory]-[DEBUG] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2017-09-26 12:10:34,707 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2017-09-26 12:10:34,707 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2017-09-26 12:10:34,707 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2017-09-26 12:10:34,707 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2017-09-26 12:10:34,763 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2017-09-26 12:10:34,954 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 239465106.
2017-09-26 12:10:34,954 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@e45f292]
2017-09-26 12:10:34,956 [main] [123.selectById]-[DEBUG] ==>  Preparing: select * from tb_student where sno = ? 
2017-09-26 12:10:34,987 [main] [123.selectById]-[DEBUG] ==> Parameters: 001(String)
2017-09-26 12:10:35,001 [main] [123.selectById]-[DEBUG] <==      Total: 1
Student [sno=001, sname=陈一]
2017-09-26 12:10:35,001 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@e45f292]
2017-09-26 12:10:35,002 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@e45f292]
2017-09-26 12:10:35,002 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 239465106 to pool.
  • ☞ 目录结构
image.png

☃ 分析

- A.步骤
  - 1.配置mybatis-config.xml 全局的配置文件 (1.数据源,2.xxxMapper.xml) 
  - 2.创建SqlSessionFactory,打开SqlSession
  - 4.通过SqlSession操作数据库 CRUD
  - 5.调用sqlSession.commit()提交事务(增删改)
  - 6.调用sqlSession.close()关闭会话
- B.注意事项
  - 1.这里直接使用SqlSession进行CRUD,可以使用Mapper接口和其实现类,也可以使用动态代理方式(底层都是sqlSession)
  - 2.因为没有写Mapper接口,映射文件的namespace名和statementId是随意取得,只要保证namespace唯一&&该namespace下该id唯一即可。一般与Mapper接口一致
②HelloWorld(完整xml版)

完整版在最简版的基础上:a.删除了测试类;b.增加Mapper接口和实现类;c.使用单元测试用例

  • ☞ 导入Junit4依赖
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
  • ☞ Mapper接口和实现类
public interface StudentMapper {
    //@Select("select * from tb_student where sno = #{sno}")
    public Student selectById(String sno);
    
    public List<Student> selectAll();
    
    public int selectCount();
    
    //CUD默认返回int(影响条数,batchUpdate似乎不行),直接Integer接收不需要设置resultType;若要返回主键需要Statement标签中设置
    public Integer insertStu(Student student);
    
    public Integer updateStu(Student student);
    
    public void deleteById(String sno);
}
public class StudentMapperImpl implements StudentMapper {

    public SqlSession sqlSession;
    
    //有参构造
    public StudentMapperImpl(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    public Student selectById(String sno) {
        return this.sqlSession.selectOne("123.selectById", sno);
    }

    public List<Student> selectAll() {
        return this.sqlSession.selectList("123.selectAll");
    }
    
    public int selectCount() {
        return this.sqlSession.selectOne("123.selectCount");
    }
    
    //CUD默认返回int(影响条数),要返回主键需要Statement标签中设置
    public Integer insertStu(Student student) {
        return this.sqlSession.insert("123.insert", student);
        
    }

    public Integer updateStu(Student student) {
        return this.sqlSession.update("123.update", student);
    }

    public void deleteById(String sno) {
        this.sqlSession.delete("123.delete", sno);
    }
}

☞ StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="123">

    <select id="selectById" resultType="com.top.test.pojo.Student">
        select * from tb_student where sno = #{sno};
    </select>
    
    <select id="selectAll" resultType="com.top.test.pojo.Student">
        select * from tb_student;
    </select>
    
    <!-- 返回int/integer都可以,integer也可以用int接,但一般对应起来都用integer -->
    <select id="selectCount" resultType="Integer">
        select count(*) from tb_student;
    </select>
    
    <insert id="insert" parameterType="com.top.test.pojo.Student">
        insert into tb_student(
            sno,
            sname
        )
        values(
            #{sno},
            #{sname}
        );
    </insert>
    
    <update id="update" parameterType="com.top.test.pojo.Student">
        upadte tb_student set
            sname = #{sname}
        where
            sno = #{sno};
    </update>
    
    <delete id="delete" parameterType="String">
        delete from tb_student where sno = #{sno};
    </delete>
    
</mapper>

这里的namespace和id是随意取得,一般和Mapper接口方法一致;使用动态代理时必须要一致

  • ☞ 测试用例
public class StudentMapperTest {
    public SqlSession sqlSession;
    public StudentMapper studentMapper;
    
    @Before
    //@Test方法执行前执行该方法
    public void setUp() throws Exception {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //不能自己加SqlSession sqlSession(加了就是局部变量,setUp执行后就没了),所以要使用成员变量,不能自己new一个引用
        this.sqlSession = sqlSessionFactory.openSession();
        //同上;通过有参构造传入sqlSession
        this.studentMapper = new StudentMapperImpl(sqlSession);
    }

    @Test
    public void testSelectById() {
        Student student = this.studentMapper.selectById("001");
        System.out.println(student);
    }

    @Test
    public void testSelectAll() {
        List<Student> list = this.studentMapper.selectAll();
        for (Student student : list) {
            System.out.println(student);
        }
    }
    
    @Test
    public void testSelectCount() {
        int count = this.studentMapper.selectCount();
        System.out.println(count);
    }

    @Test
    public void testInsertStu() {
        Student student = new Student();
        student.setSno("006");
        student.setSname("周六");
        Integer count = this.studentMapper.insertStu(student);
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
        System.out.println(count);
    }

    @Test
    public void testUpdateStu() {
        Student student = new Student();
        student.setSno("006");
        student.setSname("赵七");
        Integer count = this.studentMapper.updateStu(student);
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
        System.out.println(count);
    }

    @Test
    public void testDeleteById() {
        this.studentMapper.deleteById("006");
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
    }
}

sqlSession本身的两个实现类是线程不安全的(mybatis-spring提供的SqlSessionTemplate是线程安全的实现),所以这里生命周期最好是一个线程(如一次request-response)/方法内-局部变量

  • ☞ 目录结构
image.png

☃ 分析执行顺序

- 1.Run as,会先执行@Before方法
  - 创建sqlSession(加载主配置文件mybatis-config.xml),赋值给成员变量引用
  - 实例StudentMapperImpl(传sqlSession)
- 2.再执行StudentMapperTest中的@Test方法
  - 测试StudentMapperImpl的方法-->也就是sqlSession执行相应的statement
- 3.提交,数据库更新
③HelloWorld(动态代理版)

因为在DAO/Mapper的实现类中对sqlsession的使用方式很类似。mybatis提供了接口的动态代理(懒)

  • 在②中:接口->实现类->mapper.xml,在实现类中完成接口方法和statement的对应(namespace.id);
  • 接口的动态代理版不写实现类,如何完成接口方法和statement的对应:
    四个约定
     ➢ namespace名称 = 接口Mapper/DAO的全类名
     ➢ statement的id = 接口Mapper/DAO的方法名
     ➢ resultType = mapper接口方法的返回类型
     ➢ parameterType = mapper接口方法的参数类型(也可省略不写)
使用动态代理改造CRUD

a.删除DAO/Mapper接口实现类;b.满足四个约定;c.修改单元测试(接口方法-Statement的映射方式)

  • ☞ 修改后的StudentMapper.xml(namespace和statementId)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.top.test.mapper.StudentMapper">
    <select id="selectById" resultType="com.top.test.pojo.Student">
        select * from tb_student where sno = #{sno};
    </select>
    
    <select id="selectAll" resultType="com.top.test.pojo.Student">
        select * from tb_student;
    </select>
    
    <!-- 返回int/integer都可以,integer也可以用int接,但一般对应起来都用integer -->
    <select id="selectCount" resultType="Integer">
        select count(*) from tb_student;
    </select>
    
    <insert id="insertStu" parameterType="com.top.test.pojo.Student">
        insert into tb_student(
            sno,
            sname
        )
        values(
            #{sno},
            #{sname}
        );
    </insert>
    
    <update id="updateStu" parameterType="com.top.test.pojo.Student">
        upadte tb_student set
            sname = #{sname}
        where
            sno = #{sno};
    </update>
    
    <delete id="deleteById" parameterType="String">
        delete from tb_student where sno = #{sno};
    </delete>   
</mapper>
  • ☞ 修改后的测试用例
public class StudentMapperTest {
    public SqlSession sqlSession;
    public StudentMapper studentMapper;
    
    @Before
    //@Test方法执行前执行该方法
    public void setUp() throws Exception {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //不能自己加SqlSession sqlSession(加了就是局部变量,setUp执行后就没了),所以要使用成员变量,不能自己new一个赋给引用
        this.sqlSession = sqlSessionFactory.openSession();
        //this.studentMapper = new StudentMapperImpl(sqlSession);//同上;通过有参构造传入sqlSession
        //同上;动态代理方式
        this.studentMapper = this.sqlSession.getMapper(StudentMapper.class);
    }

    @Test
    public void testSelectById() {
        Student student = this.studentMapper.selectById("001");
        System.out.println(student);
    }

    @Test
    public void testSelectAll() {
        List<Student> list = this.studentMapper.selectAll();
        for (Student student : list) {
            System.out.println(student);
        }
    }
    
    @Test
    public void testSelectCount() {
        int count = this.studentMapper.selectCount();
        System.out.println(count);
    }

    @Test
    public void testInsertStu() {
        Student student = new Student();
        student.setSno("006");
        student.setSname("周六");
        Integer count = this.studentMapper.insertStu(student);
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
        System.out.println(count);
    }

    @Test
    public void testUpdateStu() {
        Student student = new Student();
        student.setSno("006");
        student.setSname("赵七");
        Integer count = this.studentMapper.updateStu(student);
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
        System.out.println(count);
    }

    @Test
    public void testDeleteById() {
        this.studentMapper.deleteById("006");
        this.sqlSession.commit();//不提交不生效;使用重载方法可以自动提交事务
    }
}
  • ☞ 目录结构


    image.png
  • 数据库字段名和实体类属性名不一致

    • 语句中使用别名
    • resultMap中对应
    • mybatis-config.xml中开启驼峰匹配(约定)
☠ MyBatis HelloWorld Done☠

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,425评论 0 4
  • 11 MyBatis一级缓存实现# 11.1 什么是一级缓存? 为什么使用一级缓存?## 每当我们使用MyBati...
    七寸知架构阅读 10,831评论 12 143
  • 1 引言# 本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybait...
    七寸知架构阅读 76,424评论 36 980
  • 走,沿着这条路,一直走下去,走下去,走下去,走到没有了路,再倘出一条路,直到时空的尽头…… PS:既然心已经死了,...
    二刚的轨迹阅读 185评论 1 0
  • 看了很多日本的推理小说,感觉没一个是真的在写推理小说的,几乎都是将之作为一个载体,去描绘当下的社会人情或是不同区域...
    晨昏飞行阅读 257评论 0 0