一、ResultMap的association与collection association与collection功能相似,区别是一对一与一对多,这里以association为例。java
首先说明一下需求:经过员工ID获取员工信息,同时获取员工的角色,涉及到了员工信息表、角色表、还有两者的关联表。最简单的作法是写一个SQL语句,语句里写了三个表,互相关联进行查询,但这种方式存在问题:一、SQL语句不易维护 二、复用性不强 三、我只想获取用户的信息,不用角色信息时,查询了多余的信息,徒增消耗。sql
解决办法:一、对每一个实体都定义一个基础的ResultMap,根据须要继承基础ResultMap再添加自定义的属性 二、在ResultMap中使用association或者collection进行关联查询 三、使用延迟加载,须要角色信息时再去查询。mybatis
实际操做过程:app
新建实体类User和Role测试
import java.util.Date; public class Role { private Long id; private String roleName; private Integer enabled; private Long createBy; private Date createTime; private Long updateBy; private Date updateTime; ... getter和setter就省略了 ... }
import java.util.Date; import java.util.List; public class User { private Long id; private String userName; private String userPassword; private String userPhone; private String userEmail; private Date createTime; private Date updateTime; private byte[] headImg; private Role role; ... getter和setter省略了 ... }
而后编写Mapper.xmlfetch
首先先编写其中的字段映射部分BaseResultMap。spa
UserMapper.xmlrest
<resultMap id="BaseResultMap" type="com.forest.owl.entity.User"> <id column="id" jdbcType="BIGINT" property="id" /> <result column="user_name" jdbcType="VARCHAR" property="userName" /> <result column="user_password" jdbcType="VARCHAR" property="userPassword" /> <result column="user_phone" jdbcType="VARCHAR" property="userPhone" /> <result column="user_email" jdbcType="VARCHAR" property="userEmail" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> <result column="head_img" jdbcType="LONGVARBINARY" property="headImg" /> </resultMap>
RoleMapper.xmlcode
<resultMap id="BaseResultMap" type="com.forest.owl.entity.Role"> <id column="id" jdbcType="BIGINT" property="id" /> <result column="role_name" jdbcType="VARCHAR" property="roleName" /> <result column="enabled" jdbcType="INTEGER" property="enabled" /> <result column="create_by" jdbcType="BIGINT" property="createBy" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_by" jdbcType="BIGINT" property="updateBy" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> </resultMap>
编写RoleMapper.xml获取Role的接口和XMLxml
import com.forest.owl.entity.Role; public interface RoleMapper { Role selectByPrimaryKey(Long id); }
RoleMapper.xml
<select id="selectByPrimaryKey" resultMap="BaseResultMap"> select id, role_name, enabled, create_by, create_time, update_by, update_time from role where id = #{id,jdbcType=BIGINT} </select>
而后编写UserMapper.xml
<resultMap id="UserAndRole" extends="BaseResultMap" type="com.forest.owl.entity.User"> <association property="role" fetchType="lazy" column="{id=role_id}" select="com.forest.owl.mapper.RoleMapper.selectByPrimaryKey"/> </resultMap> <select id="selectUsersById" resultMap="UserAndRole"> SELECT u.*, ur.role_id FROM user u INNER JOIN user_role ur on ur.user_id=u.id WHERE u.id=#{id} </select>
能够看到,UserMapper的SQL语句中少了role表,这样SQL语句就简洁多了。须要注意,association中的fetchType=“lazy”选项,当执行getRole()的时候,才回去查询角色信息加载到查询结果中。若是用户仍是须要在触发某个方法时加载所有数据,则能够配置mybatis的配置选项lazyLoadTriggerMethods,按需加载。
对于3.4.1 及以前版本的mybatis用户,还须要配置mybatis-config.xml的一个选项:
<setting name="aggressiveLazyLoading" value="false"/>
测试:
@Test public void UserMapperTest(){ SqlSession sqlSession = getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.selectUsersById((long) 2); System.out.println(userList.size()); System.out.println("--------getRole---------"); System.out.println(userList.get(0).getRole()); }
执行结果
collection的代码
import java.util.Date; import java.util.List; public class User { private Long id; private String userName; private String userPassword; private String userPhone; private String userEmail; private Date createTime; private Date updateTime; private byte[] headImg; private List<Role> roleList; ... getter和setter省略 ... }
<?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.forest.owl.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.forest.owl.entity.User"> <id column="id" jdbcType="BIGINT" property="id" /> <result column="user_name" jdbcType="VARCHAR" property="userName" /> <result column="user_password" jdbcType="VARCHAR" property="userPassword" /> <result column="user_phone" jdbcType="VARCHAR" property="userPhone" /> <result column="user_email" jdbcType="VARCHAR" property="userEmail" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> <result column="head_img" jdbcType="LONGVARBINARY" property="headImg" /> </resultMap> <resultMap id="UserAndRole" extends="BaseResultMap" type="com.forest.owl.entity.User"> <collection property="roleList" columnPrefix="role_" fetchType="lazy" resultMap="com.forest.owl.mapper.RoleMapper.BaseResultMap"> <id property="id" column="id"/> <result column="role_name" property="roleName" /> <result column="enabled" property="enabled" /> <result column="create_by" property="createBy" /> <result column="create_time" property="createTime" /> <result column="update_by" property="updateBy" /> <result column="update_time" property="updateTime" /> </collection> </resultMap> <select id="selectUsersById" resultMap="UserAndRole"> SELECT u.*, r.id role_id, r.role_name role_role_name, r.enabled role_enabled, r.create_by role_create_by, r.create_time role_create_time, r.update_by role_update_by, r.update_time role_update_time FROM user u INNER JOIN user_role ur on ur.user_id=u.id INNER JOIN role r on r.id=ur.role_id WHERE u.id=#{id} </select> </mapper>
UserMapper接口
import com.forest.owl.entity.User; public interface UserMapper { User selectUsersById(Long id); }
@Test public void UserMapperTest(){ SqlSession sqlSession = getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectUsersById((long) 2); System.out.println(user.getRoleList().get(0).getRoleName()); System.out.println(user.getRoleList().get(1).getRoleName()); }