Mybatis 的级联
使用 association 处理一对一关联关系
association: 映射到 JavaBean 的某个“复杂类型”属性,比如 JavaBean 类,即在 JavaBean 内部嵌套一个 复杂类型JavaBean属性。
association使用方法:
User.java
package sqlmapper;
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String telephone;
private Integer userrole;
private Role role;
...此处省略setter和getter方法
}
Role.java
package sqlmapper;
public class Role {
private Integer roleId;
private String roleName;
private String roleCode;
...此处省略setter和getter方法
}
比较简单且关联不多的场景
- 在UserMapper.xml 中,由于 User 对象内部嵌套JavaBean 对象(Role),因此需要使用 association 类实现结果映射。
<resultMap id="userRoleResult" type="sqlmapper.User">
<id property="id" column="id" />
<result property="username" column="username" />
<association property="role" javaType="sqlmapper.Role" resultMap="BaseResultMap"/>
</resultMap>
<resultMap id="BaseResultMap" type="sqlmapper.Role">
<id column="roleId" property="roleId" />
<result column="roleName" property="roleName" />
<result column="roleCode" property="roleCode" />
</resultMap>
也可以这样写:
<resultMap id="userRoleResult" type="sqlmapper.User">
<id property="id" column="id" />
<result property="username" column="username" />
<association property="role" javaType="sqlmapper.Role" >
<id column="roleId" property="roleId" />
<result column="roleName" property="roleName" />
<result column="roleCode" property="roleCode" />
</association>
</resultMap>
简单分析 association 的属性:
- javaType:完整Java类名或者别名。
- property:映射到数据路列的实体对象的属性,此处为在 User 里定义的属性:role
association 的子元素如下:
- property:映射到数据库里的实体对象的属性。此处为Role的属性。
- column:数据库列名
复杂且关联较多的场景
Role 对应的Mapper 文件:RoleMapper.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="sqlmapper.RoleMapper">
<select id="getRoleById" resultType="sqlmapper.Role" parameterType="int">
select * from role where roleId=#{id}
</select>
</mapper>
User 对应的Mapper 文件:UserMapper.xml
<resultMap id="userRoleResults" type="sqlmapper.User">
<id property="id" column="id" />
<result property="username" column="username" />
<association property="role" column="userRole" select="sqlmapper.RoleMapper.getRoleById"/>
</resultMap>
<select id="getUserById" resultMap="userRoleResults"
parameterType="int">
select *
from user
where id=#{id}
</select>
- property:代表映射到 POJO 属性上。
- select:select 配置是命名空间+SQL id 形式,这样便可以指向对应 Mapper 的 SQL,Mybatis 就会通过对应的 SQL 将数据查询回来。
- column:代表SQL的列,用作参数传递给 select 属性制定的 SQL ,如果是多个参数,则需要用逗号隔开。
使用 collection 处理一对一关联关系
collection 元素的作用其实跟 association 差不多,只是 collection 只是映射到 JavaBean 的某个属性是一个类的列表。
如在User 类中增加个Address的列表属性:
private List<Address> addressList;
则使用 collection 来映射。UserMapper.xml 关键代码如下:
<resultMap id="userRoleResult" type="sqlmapper.User">
<id property="id" column="id" />
<result property="username" column="username" />
<association property="addressList" ofType="sqlmapper.Address" >
<id column="id" property="aid" />
<result column="postCode" property="postCode" />
<result column="tel" property="tel" />
</association>
</resultMap>
跟 association 的用法差不多,就是 association 中的 javaType 改成 ofType 而已。
Mybatis 的加载延迟
Mybatis 支持延迟加载,我们希望一次性把常用的级联数据(针对association 和 collection)通过 SQL 直接查询出来,而对于那些不常用的级联数据不要取出,而是等待要用时才取出,这些不常用的级联数据可以采用延迟加载的功能。
在Mybatis 的 settings 配置中配置是否加载延迟:
<setting >
<setting name="lazyLoadingEnabled" value="true">
<setting name="aggressiveLazyLoading" value="false"> #为false启动按需加载
</setting >
- 选项 lazyLoadingEnabled 决定是否开启延迟加载,
- 而选项 aggressiveLazyLoading 为 true 的时候,一加载对象(任何一个属性)就会加载他的全部属性(如:调用User对象的任何一个属性的时候就为这个User对象加载它的 role 属性)。为 false 的时候,就是按需加载,调用User对象 的 role属性时才会去数据库查询并加载它的 role 属性的数据。
此外, Mybatis 中 还有 fetchType 属性。它存在两个值。
- eager:获得当前POJO 后立即加载对应的数据。
- lazy:获得当前POJO后延迟加载对应的数据。
如:
<resultMap id="userRoleResults" type="sqlmapper.User">
<id property="id" column="id" />
<result property="username" column="username" />
<association property="role" column="userRole" fetchType="eager" select="sqlmapper.RoleMapper.getRoleById"/>
</resultMap>
这样就会初始化对象的时候就为这个对象加载它的 role 属性。改成 fetchType=“lazy” 则调用User 的 role属性时才会加载它的 role 属性的数据。
fetchType 属性会忽略全局配置项 lazyLoadingEnabled 和 aggressiveLazyLoading 的配置。