mybatis进阶2——关联查询

关联查询代码参考mybatis-demo
测试代码AssociationQueryTest.java

0.关联查询的应用场景

适用于传统软件,对于高并发、数据量巨大的互联网应用,要慎用!



1.关联查询概览

在关系型数据库中,关联元素是专门处理关联关系的。如:一辆汽车需要一个引擎,这是一对一的关系。一辆汽车需要4个或更多的轮子,这是一对多的关系。

  • 关联元素
    association 一对一关系
    collection 一对多关系
    discriminator 鉴别器映射

  • 关联方式
    嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集(一个SQL语句)
    嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型(多个SQL语句)

  • 嵌套结果示例

SELECT a.id, 
       a.user_name,
       a.real_name,
       a.sex,
       a.mobile,
       b.comp_name,
       b.years,
       b.title
FROM t_user a,
     t_job_history b
WHERE a.id = b.`user_id`
  • 嵌套查询实例
SELECT a.id, 
       a.user_name,
       a.real_name,
       a.sex,
       a.mobile
FROM t_user a;
     
SELECT b.comp_name,
       b.years,
       b.title
FROM  t_job_history b
WHERE b.`user_id`=3;

2.一对一关联查询

2.1 嵌套结果

association标签 嵌套结果方式 常用属性:

  • property:对应实体类中的属性名,必填项
  • javaType:属性对应的Java类型
  • resultMap:可以直接使用现有的resultMap,而不需要在这里配置映射关系
  • columnPrefix:查询列的前缀,配置前缀后,在子标签配置result的column时可以省略前缀

Tips:

  • resultMap可以通过使用extends实现继承关系,简化很多配置作用
  • 关联的表查询的类添加前缀是编程的好习惯
  • 通过添加完整的命名空间,可以引用其他xml文件的resultMap
    <select id="selectUserPosition1" resultMap="userAndPosition1">
        select
            a.id, 
            user_name,
            real_name,
            sex,
            mobile,
            email,
            a.note,
            b.id  post_id,
            b.post_name,
            b.note post_note
        from t_user a,
            t_position b
        where a.position_id = b.id
    </select>
    <resultMap id="userAndPosition1" extends="BaseResultMap" type="TUser">
        <association property="position" javaType="TPosition" columnPrefix="post_">
            <id column="id" property="id"/>
            <result column="name" property="postName"/>
            <result column="note" property="note"/>
        </association>
    </resultMap>

测试代码:

    @Test
    // 1对1两种关联方式
    public void testOneToOne() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        // ----------------------
        List<TUser> list1 = mapper.selectUserPosition1();
        for (TUser tUser : list1) {
            System.out.println(tUser);
        }
    }

测试准备:
1)generatorConfig.xml自动生成相应的代码
2)修改TUser等代码
3)添加mapper映射

    <!-- 映射文件,mapper的配置文件 -->
    <mappers>
        <!--直接映射到相应的mapper文件 -->
        <mapper resource="sqlmapper/TUserMapper.xml" />
        <mapper resource="sqlmapper/TJobHistoryMapper.xml" />
        <mapper resource="sqlmapper/TPositionMapper.xml" />
        <mapper resource="sqlmapper/THealthReportFemaleMapper.xml" />
        <mapper resource="sqlmapper/THealthReportMaleMapper.xml" />
         <mapper class="com.enjoylearning.mybatis.mapper.TJobHistoryAnnoMapper"/>
    </mappers>

测试结果:

2018-09-25 08:18:52.291 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition1 - ==>  Preparing: select a.id, user_name, real_name, sex, mobile, email, a.note, b.id post_id, b.post_name, b.note post_note from t_user a, t_position b where a.position_id = b.id 
2018-09-25 08:18:52.377 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition1 - ==> Parameters: 
2018-09-25 08:18:52.445 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition1 - <==      Total: 5
TUser [id=1, userName=lison, realName=李小宇, sex=1, mobile=186995587422, email=lison@qq.com, note=lison的备注, positionId=1]
TUser [id=3, userName=cindy, realName=王美丽, sex=2, mobile=18695988747, email=xxoo@163.com, note=cindy's note, positionId=1]
TUser [id=126, userName=mark, realName=毛毛, sex=1, mobile=18695988747, email=xxoo@163.com, note=mark's note, positionId=1]
TUser [id=131, userName=mark, realName=毛毛, sex=1, mobile=18695988747, email=xxoo@163.com, note=mark's note, positionId=1]
TUser [id=2, userName=james, realName=陈大雷, sex=1, mobile=18677885200, email=james@qq.com, note=james的备注, positionId=2]

2.2 嵌套查询

association标签 嵌套查询方式 常用属性:

  • select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果
  • column:列名(或别名),将主查询中列的结果作为嵌套查询的参数
  • fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载,这个配置会覆盖全局的lazyLoadingEnabled配置
    <select id="selectUserPosition2" resultMap="userAndPosition2">
        select
        a.id,
        a.user_name,
        a.real_name,
        a.sex,
        a.mobile,
        a.position_id
        from t_user a
    </select>
    <resultMap id="userAndPosition2" extends="BaseResultMap" type="TUser">
        <association property="position" fetchType="lazy"  column="position_id" select="com.enjoylearning.mybatis.mapper.TPositionMapper.selectByPrimaryKey" />
    </resultMap>

其中:TPositionMapper.xml中的selectByPrimaryKey如下:

  <sql id="Base_Column_List">
    <!--
      WARNING - @mbg.generated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    id, post_name, note
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    <!--
      WARNING - @mbg.generated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    select 
    <include refid="Base_Column_List" />
    from t_position
    where id = #{id,jdbcType=INTEGER}
  </select>

测试代码:

    @Test
    // 1对1两种关联方式
    public void testOneToOne() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        // ----------------------
//      List<TUser> list1 = mapper.selectUserPosition1();
//      for (TUser tUser : list1) {
//          System.out.println(tUser);
//      }

        List<TUser> list2 = mapper.selectUserPosition2();
        for (TUser tUser : list2) {
            System.out.println(tUser.getPosition().getPostName());
        }
    }

测试结果:

2018-09-25 09:07:30.292 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - ==>  Preparing: select a.id, a.user_name, a.real_name, a.sex, a.mobile, a.position_id from t_user a 
2018-09-25 09:07:30.374 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - ==> Parameters: 
2018-09-25 09:07:30.428 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ====>  Preparing: select id, post_name, note from t_position where id = ? 
2018-09-25 09:07:30.429 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ====> Parameters: 1(Integer)
2018-09-25 09:07:30.438 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - <====      Total: 1
2018-09-25 09:07:30.439 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ====>  Preparing: select id, post_name, note from t_position where id = ? 
2018-09-25 09:07:30.440 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ====> Parameters: 2(Integer)
2018-09-25 09:07:30.442 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - <====      Total: 1
2018-09-25 09:07:30.449 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - <==      Total: 4
总经理
零时工
总经理
总经理

非懒加载的情况:


注意:这里只进行了三次查询,为什么不是N+1=5?
这里跟缓存有关,总经理值查了一次。

setting里面的属性

Tips:N+1查询问题

  • 问题描述:执行了一个单独SQL语句来获取结果列表(就是+1);对返回的每条记录,执行一个查询语句来为每条记录加载细节(就是N)。这个问题会导致成百上千的SQL语句被执行。
  • 解决方法:使用fetchType=lazy并且全局setting进行改善
<setting name="aggressiveLazyLoading" value="false"/>
2018-09-25 09:26:46.470 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - ==>  Preparing: select a.id, a.user_name, a.real_name, a.sex, a.mobile, a.position_id from t_user a 
2018-09-25 09:26:46.499 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - ==> Parameters: 
2018-09-25 09:26:46.557 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserPosition2 - <==      Total: 4
2018-09-25 09:26:46.558 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ==>  Preparing: select id, post_name, note from t_position where id = ? 
2018-09-25 09:26:46.577 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ==> Parameters: 1(Integer)
2018-09-25 09:26:46.578 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - <==      Total: 1
总经理
2018-09-25 09:26:46.578 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ==>  Preparing: select id, post_name, note from t_position where id = ? 
2018-09-25 09:26:46.579 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - ==> Parameters: 2(Integer)
2018-09-25 09:26:46.582 [main] DEBUG c.e.m.mapper.TPositionMapper.selectByPrimaryKey - <==      Total: 1
零时工
总经理
总经理

懒加载情况:


3.一对多关联查询

  • collection支持的属性以及属性的作用和association完全相同
  • mybatis会根据id标签,进行字段的合并,合理配置好ID标签可以提高处理的效率

Tips:
如果要配置一个相当复杂的映射,一定要从基础映射开始配置,每增加一些配置就进行对应的测试,在循序渐进的过程中更容易发现和解决问题。

3.1 嵌套结果

    <select id="selectUserJobs1" resultMap="userAndJobs1">
        select
        a.id,
        a.user_name,
        a.real_name,
        a.sex,
        a.mobile,
        b.comp_name,
        b.years,
        b.title
        from t_user a,
        t_job_history b
        where a.id = b.user_id
    </select>
    <resultMap id="userAndJobs1" extends="BaseResultMap" type="TUser">
        <collection property="jobs"
                    ofType="com.enjoylearning.mybatis.entity.TJobHistory" >
            <result column="comp_name" property="compName" jdbcType="VARCHAR" />
            <result column="years" property="years" jdbcType="INTEGER" />
            <result column="title" property="title" jdbcType="VARCHAR" />
        </collection>
    </resultMap>

测试程序:

    @Test
    // 1对多两种关联方式
    public void testOneToMany() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        // ----------------------
        List<TUser> selectUserJobs1 = mapper.selectUserJobs1();
//        List<TUser> selectUserJobs2 = mapper.selectUserJobs2();
        for (TUser tUser : selectUserJobs1) {
            System.out.println(tUser);
        }
//        for (TUser tUser : selectUserJobs2) {
//            System.out.println(tUser.getJobs().size());
//        }
    }

测试结果:

2018-09-25 09:50:43.860 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs1 - ==>  Preparing: select a.id, a.user_name, a.real_name, a.sex, a.mobile, b.comp_name, b.years, b.title from t_user a, t_job_history b where a.id = b.user_id 
2018-09-25 09:50:43.921 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs1 - ==> Parameters: 
2018-09-25 09:50:43.942 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs1 - <==      Total: 6
TUser [id=1, userName=lison, realName=李小宇, sex=1, mobile=186995587422, email=null, note=null, positionId=]
TUser [id=2, userName=james, realName=陈大雷, sex=1, mobile=18677885200, email=null, note=null, positionId=]
TUser [id=3, userName=cindy, realName=王美丽, sex=2, mobile=18695988747, email=null, note=null, positionId=]

3.2 嵌套查询

    <select id="selectUserJobs2" resultMap="userAndJobs2">
        select
        a.id,
        a.user_name,
        a.real_name,
        a.sex,
        a.mobile
        from t_user a
    </select>
    <resultMap id="userAndJobs2" extends="BaseResultMap" type="TUser">
        <collection property="jobs" fetchType="lazy" column="id"
                    select="com.enjoylearning.mybatis.mapper.TJobHistoryMapper.selectByUserId" />
    </resultMap>

TJobHistoryMapper.xml中的selectByUserId:

    <select id="selectByUserId" resultMap="BaseResultMap"  parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List" />
        from t_job_history
        where user_id = #{userId,jdbcType=INTEGER}
    </select>

测试程序:

    @Test
    // 1对多两种关联方式
    public void testOneToMany() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        // ----------------------
//        List<TUser> selectUserJobs1 = mapper.selectUserJobs1();
        List<TUser> selectUserJobs2 = mapper.selectUserJobs2();
//        for (TUser tUser : selectUserJobs1) {
//            System.out.println(tUser);
//        }
        for (TUser tUser : selectUserJobs2) {
            System.out.println(tUser.getJobs().size());
        }
    }

测试结果:

2018-09-25 09:52:28.543 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs2 - ==>  Preparing: select a.id, a.user_name, a.real_name, a.sex, a.mobile from t_user a 
2018-09-25 09:52:28.623 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs2 - ==> Parameters: 
2018-09-25 09:52:28.701 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectUserJobs2 - <==      Total: 4
2018-09-25 09:52:28.703 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history where user_id = ? 
2018-09-25 09:52:28.704 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==> Parameters: 1(Integer)
2018-09-25 09:52:28.705 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - <==      Total: 1
1
2018-09-25 09:52:28.706 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history where user_id = ? 
2018-09-25 09:52:28.707 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==> Parameters: 2(Integer)
2018-09-25 09:52:28.709 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - <==      Total: 2
2
2018-09-25 09:52:28.709 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history where user_id = ? 
2018-09-25 09:52:28.709 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==> Parameters: 3(Integer)
2018-09-25 09:52:28.710 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - <==      Total: 3
3
2018-09-25 09:52:28.711 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history where user_id = ? 
2018-09-25 09:52:28.711 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - ==> Parameters: 126(Integer)
2018-09-25 09:52:28.712 [main] DEBUG c.e.m.mapper.TJobHistoryMapper.selectByUserId - <==      Total: 0
0

4.discriminator鉴别器映射

在特定的情况下使用不同的POJO进行关联,鉴别器元素就是被设计来处理这个情况的。鉴别器非常容易理解,因为其表现很像Java中的switch语句。

dicriminator标签常用的两个属性如下:

  • column:用于设置要进行鉴别比较值的列
  • javaType:用于指定列的类型,保证使用相同的Java类型来比较值

discriminator标签可以有1个或多个case标签,case标签包含以下三个属性:

  • value:为discriminator指定column用来匹配的值
  • resultMap:当column值和value值匹配时,可以配置使用resultMap指定的映射,resultMap优先级高于resultType
  • resultType:当column值和value值匹配时,用于配置使用resultType指定的映射
    <resultMap id="userAndHealthReportMale" extends="userAndHealthReport" type="TUser">
        <collection property="healthReports" column="id"
                    select= "com.enjoylearning.mybatis.mapper.THealthReportMaleMapper.selectByUserId"></collection>
    </resultMap>

    <resultMap id="userAndHealthReportFemale" extends="userAndHealthReport" type="TUser">
        <collection property="healthReports" column="id"
                    select= "com.enjoylearning.mybatis.mapper.THealthReportFemaleMapper.selectByUserId"></collection>
    </resultMap>

    <resultMap id="userAndHealthReport" extends="BaseResultMap" type="TUser">
        <discriminator column="sex"  javaType="int">
            <case value="1" resultMap="userAndHealthReportMale"/>
            <case value="2" resultMap="userAndHealthReportFemale"/>
        </discriminator>
    </resultMap>


    <select id="selectUserHealthReport" resultMap="userAndHealthReport">
        select
        <include refid="Base_Column_List" />
        from t_user a
    </select>

体检报告:
TUser中

   private List<HealthReport> healthReports;

测试代码:

    @Test
    public void testDiscriminator(){
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
//      // 4.执行查询语句并返回结果
//      // ----------------------
        List<TUser> list = mapper.selectUserHealthReport();
        for (TUser tUser : list) {
            System.out.println(tUser);
        }
    }

添加com.enjoylearning.mybatis.mapper.THealthReportMaleMapper.selectByUserId,同理还有Female的。

  <select id="selectByUserId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    <!--
      WARNING - @mbg.generated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    select
    <include refid="Base_Column_List" />
    from t_health_report_male
    where user_id = #{userID,jdbcType=INTEGER}
  </select>

测试结果:

2018-09-25 10:33:43.344 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@289710d9]
2018-09-25 10:33:43.350 [main] DEBUG c.e.m.mapper.TUserMapper.selectUserHealthReport - ==>  Preparing: select id, user_name, real_name, sex, mobile, email, note, position_id from t_user a 
2018-09-25 10:33:43.391 [main] DEBUG c.e.m.mapper.TUserMapper.selectUserHealthReport - ==> Parameters: 
2018-09-25 10:33:43.410 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====>  Preparing: select id, check_project, detail, user_id from t_health_report_male where user_id = ? 
2018-09-25 10:33:43.411 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====> Parameters: 1(Integer)
2018-09-25 10:33:43.412 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - <====      Total: 3
2018-09-25 10:33:43.414 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====>  Preparing: select id, check_project, detail, user_id from t_health_report_male where user_id = ? 
2018-09-25 10:33:43.414 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====> Parameters: 2(Integer)
2018-09-25 10:33:43.415 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - <====      Total: 0
2018-09-25 10:33:43.416 [main] DEBUG c.e.m.m.THealthReportFemaleMapper.selectByUserId - ====>  Preparing: select id, item, score, user_id from t_health_report_female where user_id = ? 
2018-09-25 10:33:43.417 [main] DEBUG c.e.m.m.THealthReportFemaleMapper.selectByUserId - ====> Parameters: 3(Integer)
2018-09-25 10:33:43.418 [main] DEBUG c.e.m.m.THealthReportFemaleMapper.selectByUserId - <====      Total: 3
2018-09-25 10:33:43.419 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====>  Preparing: select id, check_project, detail, user_id from t_health_report_male where user_id = ? 
2018-09-25 10:33:43.419 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - ====> Parameters: 126(Integer)
2018-09-25 10:33:43.420 [main] DEBUG c.e.m.m.THealthReportMaleMapper.selectByUserId - <====      Total: 0
2018-09-25 10:33:43.420 [main] DEBUG c.e.m.mapper.TUserMapper.selectUserHealthReport - <==      Total: 4
TUser [id=1, userName=lison, realName=李小宇, sex=1, mobile=186995587422, email=lison@qq.com, note=lison的备注, positionId=]
TUser [id=2, userName=james, realName=陈大雷, sex=1, mobile=18677885200, email=james@qq.com, note=james的备注, positionId=]
TUser [id=3, userName=cindy, realName=王美丽, sex=2, mobile=18695988747, email=xxoo@163.com, note=cindy's note, positionId=]
TUser [id=126, userName=mark, realName=毛毛, sex=1, mobile=18695988747, email=xxoo@163.com, note=mark's note, positionId=]

5.多对多

  • 先决条件1.多对多需要一种中间表建立连接关系
  • 先决条件2.多对多关系是由两个一对多关系组成的,一对多也可用两种方式实现

参考

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

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,462评论 0 4
  • 1 Mybatis入门 1.1 单独使用jdbc编程问题总结 1.1.1 jdbc程序 上边使...
    哇哈哈E阅读 3,295评论 0 38
  • MyBatis 理论篇 [TOC] 什么是MyBatis  MyBatis是支持普通SQL查询,存储过程和高级映射...
    有_味阅读 2,889评论 0 26
  • 输出映射接下来说说有关Mapper.xml配置文件中查询标签中关于返回值类型resultType与resultMa...
    默默无痕阅读 13,791评论 1 10
  • 一晃进入千人排毒的时间已经第六天了,今天依然是幸福餐加营养素加蔬菜水果汁,还有葡萄籽油。今天的蔬菜水果依然是黄瓜...
    史真如阅读 425评论 0 0