在mybatis框架中,延迟加载与连表查询的差异

1.引子     

mybatis的延迟加载,主要应用于一个实体类中有复杂数据类型的属性,包括一对一和一对多的关系。这个种属性往往还对应着另一个数据表,而实际查询的需求不一定需要这个的表的数据,那么此时延迟加载相对于连表查询就有很大的优势,实现了按需加载的目的。这对提高访问速度和降低系统资源耗费有着很大的意义。

2.连表查询

背景: 用户实体类User中含有一个角色实体类Role的属性

实体类User中的属性

    private Integer id; // id
    private String userCode; // 用户编码
    private String userName; // 用户名称
    private String userPassword; // 用户密码
    private Integer userRole; // 用户角色,和角色表smbms_role的id字段关联对应
    private Role role; // 一对一 对应关系
    private Integer gender; // 性别
    private Date birthday; // 出生日期
    private String phone; // 电话
    private String address; // 地址
    private String userRoleName; // 用户角色名
    private Integer createdBy; // 创建者
    private Date creationDate; // 创建时间
    private Integer modifyBy; // 更新者
    private Date modifyDate; // 更新时间

实体类Role中的属性,

  private Integer id; // id
    
    private String roleCode; // 角色编码
    
    private String roleName; // 角色名称
    
    private Integer createdBy; // 创建者
    
    private Date creationDate; // 创建时间
    
    private Integer modifyBy; // 更新者
    
    private Date modifyDate;// 更新时间

xml中的sql语句映射文件

<!-- 演示 一对一 association 的连表查询 start -->

    <resultMap type="Role" id="roleMap">
        <id property="id" column="r_id" />
        <result property="roleCode" column="roleCode" />
        <result property="roleName" column="roleName" />
    </resultMap>
    <resultMap type="User" id="userRoleResult">
        <id property="id" column="id" />
        <result property="userCode" column="userCode" />
        <result property="userName" column="userName" />
        <association property="role" javaType="Role" resultMap="roleMap" />
    </resultMap>
    <!-- 根据用户表中角色id 和角色表做联表查询 -->
    <select id="getUserListByRoleId" parameterType="int" resultMap="userRoleResult">
        select u.* ,r.id as r_id,r.roleCode,r.roleName from
        smbms_user
        u,smbms_role r
        where u.userRole = #{userRoleId} and u.userRole = r.id
    </select>

<!-- 演示 一对一 association 的连表查询 end -->

 测试方法

  @Test
    public void selectUserByIdsAndRoleId()
    {
        List<User> users = sqlSession.getMapper(UserMapper.class).selectUserByIdsAndRoleId(3, Arrays.asList(4, 3, 7,12));
        for (User userElement : users)
        {
            System.out.println(userElement);
        }
    }

 3. 延迟加载

延迟加载可以在主配置文件mybatis-config.xml中配置,在这里的配置是全局配置,默认对所有查询SQL进行延迟加载处理。

<settings>
<!--启用延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!--关闭积极加载 -->
<setting name="aggressiveLazyLoading" value="false" />
</settings>

另外如果对全局配置不满意,可以在具体的SQL映射语句中添加collect或assocation标签中添加属性fetchType="lazy"(延迟加载)或fetchType="eager"(立即加载),

此处SQL加载方式将覆盖全局配置中的SQL加载方式,如伪代码

<collection property="addressList" 
ofType="Address" column="id"
    fetchType="lazy|eager"/>

xml中的sql映射代码

    
<!--演示 一对多 collection  -->
    <resultMap type="User" id="userAddressResult">
        <id property="id" column="id" />
        <result property="userCode" column="userCode" />
        <result property="phone" column="phone" />
        <result property="userName" column="userName" />
        <collection property="addressList" ofType="Address" column="id"
            select="lazyFindAddressListByUserId" fetchType="lazy"/>
    </resultMap>
    <!-- 延迟按需加载sql语句(即此sql可能不会使用) -->
    <select id="lazyFindAddressListByUserId" parameterType="int" resultType="Address">
        select * from smbms_address where userId=#{id}
    </select>
    <!-- 根据用户id获得 此用户的多个地址 -->
    <select id="getAddressListByUserId" parameterType="Integer"
        resultMap="userAddressResult">
    select  * from smbms_user where id = #{userId}
    </select>

 不使用addressList地址信息的测试方法

 @Test
    public void getAddressListByUserId()
    {
        List<User> users = sqlSession.getMapper(UserMapper.class).getAddressListByUserId(5);
        for (User userElement : users)
        {
          //不使用addressList属性
             System.out.println(userElement.getPhone() +" "+userElement.getUserCode());
           //   System.out.println(userElement);
        }
    }

 控制台显示只有一个sql语句,则实际上只查询了一张用户表

 使用addressList地址信息的测试方法

 @Test
    public void getAddressListByUserId()
    {
        List<User> users = sqlSession.getMapper(UserMapper.class).getAddressListByUserId(5);
        for (User userElement : users)
        {
            // 使用addressList属性
            // System.out.println(userElement.getPhone() +" "+userElement.getUserCode());
            System.out.println(userElement);
        }
    }

 控制台显示只有两条sql语句,则实际上只先查询了用户表,再用用户id去查询地址表

猜你喜欢

转载自www.cnblogs.com/gocode/p/lazyload-and-join-query-in-mybatis.html