resultMap的最基本作用就是是定义映射规则。
基本构成
<resultMap>
<constructor>
<idArg/>
<arg/>
</constructor>
<id/>
<result/>
<association/>
<collection/>
<discriminator>
<case/>
</discriminator>
</resultMap>
最基本用法
<resultMap type="Role" id="roleResultMap">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="note" column="note"/>
</resultMap>
type表示要映射的javabean类型,id标识本resultMap,select元素通过id使用resultMap
id元素定义主键,允许多个主键(联合主键)。可以看成特殊的result
result元素定义数据表字段到javabean属性的映射,id、result元素都有 property、column、javaType、jdbcType属性
<result property="roleName" column="role_name" javaType="java.lang.String" jdbcType="VARCHAR"/>
constructor
constructor元素通过构造函数创建即将要返回的javabean,普通的javabean一般不定义构造函数
<resultMap type="Role" id="roleResultMap">
<constructor>
<idArg column="id" javaType="java.lang.Integer"/>
<arg column="role_name" javaType="java.lang.String"/>
<arg column="note" javaType="java.lang.String"/>
</constructor>
</resultMap>
public Role(Integer id, String roleName, String note) {
this.id = id;
this.roleName = roleName;
this.note = note;
}
定义constructor时注意参数顺序和javabean构造函数参数顺序一致。
级联
关系型数据库中表可能存在一对一、一对多关系,对应association、collection。discriminator允许根据实际选择对哪个类实例化。
collection
新建数据表job(id,role_id,position,salary),假定role表中记录与job表中记录是一对一关系
新建Job.java
package com.lz.mybatis.model;
import java.math.BigDecimal;
public class Job {
private Integer id;
private Integer roleId;
private String position;
private BigDecimal salary;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Job [id=" + id + ", roleId=" + roleId + ", position=" + position + ", salary=" + salary + "]";
}
}
新建JobMapper.java
package com.lz.mybatis.mapper;
import com.lz.mybatis.model.Job;
public interface JobMapper {
Job getJobByRoleId(Integer roleId);
}
resource下新建com/lz/mybatis/mapper/jobMapper.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="com.lz.mybatis.mapper.JobMapper">
<resultMap type="Job" id="jobResultMap">
<id property="id" column="id"/>
<result property="roleId" column="role_id"/>
<result property="position" column="posistion"/>
<result property="salary" column="salary"/>
</resultMap>
<select id="getJobByRoleId" parameterType="java.lang.Integer" resultMap="jobResultMap">
select * from job where role_id = #{roleId}
</select>
</mapper>
修改Role.java
package com.lz.mybatis.model;
public class Role {
private Integer id;
private String roleName;
private String note;
private Job job;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Job getJob() {
return job;
}
public void setJob(Job job) {
this.job = job;
}
@Override
public String toString() {
return "Role [id=" + id + ", roleName=" + roleName + ", note=" + note + ", job=" + job + "]";
}
}
修改roleMapper.xml中的resultMap
<resultMap type="Role" id="roleResultMap">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="note" column="note"/>
<association property="job" column="id" javaType="Job" select="com.lz.mybatis.mapper.JobMapper.getJobByRoleId" />
</resultMap>
association中column属性表示传递给getJobByRoleId的参数,select表示执行的查询。这样,当执行getRole时,又对job进行查询,回填到Role的job属性。
从log中可以看出执行了两次sql
[DEBUG] 2017-03-21 14:16:50,420 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: select id, role_name, note from role where id = ?
[DEBUG] 2017-03-21 14:16:50,464 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: 10001(Integer)
[DEBUG] 2017-03-21 14:16:50,486 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ====> Preparing: select * from job where role_id = ?
[DEBUG] 2017-03-21 14:16:50,487 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ====> Parameters: 10001(Integer)
[DEBUG] 2017-03-21 14:16:50,491 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <==== Total: 1
[DEBUG] 2017-03-21 14:16:50,492 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <== Total: 1
Role [id=10002, roleName=Mybatis, note=Hello, Mybatis., job=Job [id=1, roleId=10002, position=teacher, salary=10000]]
另一种方法
roleMapper.xml
<resultMap type="Job" id="jobResultMap">
<id property="id" column="jobId"/>
<result property="roleId" column="role_id"/>
<result property="position" column="position"/>
<result property="salary" column="salary"/>
</resultMap>
<resultMap type="Role" id="roleResultMap">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="note" column="note"/>
<association property="job" javaType="Job" resultMap="jobResultMap"/>
</resultMap>
<sql id="roleColumns">
role.id, role.role_name, role.note, job.id jobId, job.role_id, job.position, job.salary
</sql>
<select id="getRole" parameterType="java.lang.Integer" resultMap="roleResultMap">
select <include refid="roleColumns"/>
from role left join job on role.id = job.role_id
where role.id = #{id}
</select>
注意到sql中给job的id起了别名jobId,用来区分mybatis构建role和job时使用的id。当然jobResultMap的内容可以直接放到association元素中
<resultMap type="Role" id="roleResultMap">
<id property="id" column="id" />
<result property="roleName" column="role_name" />
<result property="note" column="note" />
<association property="job" javaType="Job">
<id property="id" column="jobId" />
<result property="roleId" column="role_id" />
<result property="position" column="position" />
<result property="salary" column="salary" />
</association>
</resultMap>
resultMap是mybatis使用中的难点,需要熟练掌握。