1、前言
在之前的博客中,实体类的属性名和数据库表的字段名是一致的,因此能正确地查询出所需要的数据。当实体类的属性名与数据库表的字段名不一致时,会导致查询出来的数据为空指针。要解决这个问题就需要使用resultMap自定义映射。
使用的表分别为:t_minister、t_dutie,结构如下:
使用的实体类分别为:Minister类
public class Minister {
private Integer id;
private String ministerName;
private String age;
private char gender;
private Integer ministerDutie;
private Dutie dutie;
public Minister() {
}
public Minister(Integer id, String ministerName, String age, char gender, Integer ministerDutie) {
this.id = id;
this.ministerName = ministerName;
this.age = age;
this.gender = gender;
this.ministerDutie = ministerDutie;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMinisterName() {
return ministerName;
}
public void setMinisterName(String ministerName) {
this.ministerName = ministerName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Integer getMinisterDutie() {
return ministerDutie;
}
public void setMinisterDutie(Integer ministerDutie) {
this.ministerDutie = ministerDutie;
}
@Override
public String toString() {
return "Minister{" +
"id=" + id +
", ministerName='" + ministerName + '\'' +
", age='" + age + '\'' +
", gender=" + gender +
", ministerDutie='" + ministerDutie + '\'' +
", dutie=" + dutie +
'}';
}
}
Dutie类
public class Dutie {
private Integer dutieId;
private String dutieName;
public Dutie() {
}
public Dutie(Integer dutieId, String dutieName) {
this.dutieId = dutieId;
this.dutieName = dutieName;
}
public Integer getDutieId() {
return dutieId;
}
public void setDutieId(Integer dutieId) {
this.dutieId = dutieId;
}
public String getDutieName() {
return dutieName;
}
public void setDutieName(String dutieName) {
this.dutieName = dutieName;
}
@Override
public String toString() {
return "Dutie{" +
"dutieId=" + dutieId +
", dutieName='" + dutieName + '\'' +
'}';
}
}
2、resultMap处理字段和属性的映射关系
对于查询操作,若字段名和实体类中的属性名一致时,可以通过resultType指定结果类型;若字段名和实体类中的属性名不一致,则通过resultMap设置自定义映射。
若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性 名符合Java的规则(使用驼峰),此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系。
2.1 通过resultMap为字段起别名的方式,保证和实体类中的属性名保持一致。
在MinisterMapper接口中声明方法getMalMinisterByVague(@Param("gender") String gender),该方法的返回值类型为List集合,List集合中存储Minister类型的数据,采用@Param注解的方式获取参数。
//采用模糊查询,查找性别为男的人员
List<Minister> getMalMinisterByVague(@Param("gender") String gender);
在映射文件中实现Sql语句,采用resultMap自定义映射。通过resultMap的value值匹配自定义映射resultMap中id的value值。
<!-- List<Minister> getMalMinisterByVague(@Param("gender") String gender);-->
<select id="getMalMinisterByVague" resultMap="MinisterMaperr">
select *from t_minister where gender like '%${gender}%'
</select>
对于自定义映射resultMap标签,resultMap:设置自定义映射
属性: id:表示自定义映射的唯一标识 type:查询的数据要映射的实体类的类型
子标签: id:设置主键的映射关系 result:设置普通字段的映射关系
子标签中的属性: property:实体类的属性名 column:表的字段名
<resultMap id="MinisterMaperr" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="ministerDutie" column="minister_dutie"></result>
</resultMap>
完整的映射文件:
<!-- List<Minister> getMalMinisterByVague(@Param("gender") String gender);-->
<select id="getMalMinisterByVague" resultMap="MinisterMaperr">
select *from t_minister where gender like '%${gender}%'
</select>
<resultMap id="MinisterMaperr" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="ministerDutie" column="minister_dutie"></result>
</resultMap>
2.2在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase
可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰。
例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为 userName。
此时不需要使用resultMap自定义映射,只需要使用resultType指定结果类型即可。
在MinisterMapper接口中声明方法getMaleMinisterByProfile(@Param("gender") String gender),该方法的返回值类型为List集合,List集合中存储Minister类型的数据,采用@Param注解的方式获取参数。
//通过配置文件,使用模糊查询获得所有男性人员信息
List<Minister> getMaleMinisterByProfile(@Param("gender") String gender);
在映射文件中实现Sql语句,采用resultType指定结果类型。
<!-- List<Minister> getMaleMinisterByProfile(@Param("gender") String gender);-->
<select id="getMaleMinisterByProfile" resultType="Minister">
select *from t_minister where gender like '%${gender}%'
</select>
3、 多对一映射
3.1 前置工作
在MinisterMapper类中添加一个private Dutie dutie属性,添加对应的GET和SET方法,重写toString方法。
3.2 级联方式处理映射关系
在MinisterMapper接口中声明方法getGeneralMinisterByCascade(@Param("ministerDutie") Integer ministerDutie),该方法的返回值类型为List集合,List集合中存储Minister类型的数据,采用@Param注解的方式获取参数。
//查询职称为武将的人员信息,级联方式实现多对一映射
List<Minister> getGeneralMinisterByCascade(@Param("ministerDutie") Integer ministerDutie);
在映射文件中实现Sql语句,采用resultMap自定义映射。通过resultMap的value值匹配自定义映射resultMap中id的value值
<!-- List<Minister> getGeneralMinisterByCascade(@Param("ministerDutie") Integer ministerDutie);-->
<select id="getGeneralMinisterByCascade" resultMap="GeneralMinisterByCascade">
select t_minister.*,t_dutie.* from t_minister left join t_dutie on t_minister.minister_dutie=t_dutie.dutie_id where t_minister.minister_dutie=#{ministerDutie}
</select>
配置文件中property="dutie.dutieId"h和property="dutie.dutieName"中的dutie是Minister类的属性名dutie,”.“后的属性名是Dutie类中的属性名;column="dutie_id"和column="dutie_name"中的value值对应的是t_dutie表的字段名。
<resultMap id="GeneralMinisterByCascade" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<result property="dutie.dutieId" column="dutie_id"></result>
<result property="dutie.dutieName" column="dutie_name"></result>
</resultMap>
完整的映射文件:
<!-- List<Minister> getGeneralMinisterByCascade(@Param("ministerDutie") Integer ministerDutie);-->
<select id="getGeneralMinisterByCascade" resultMap="GeneralMinisterByCascade">
select t_minister.*,t_dutie.* from t_minister left join t_dutie on t_minister.minister_dutie=t_dutie.dutie_id where t_minister.minister_dutie=#{ministerDutie}
</select>
<resultMap id="GeneralMinisterByCascade" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<result property="dutie.dutieId" column="dutie_id"></result>
<result property="dutie.dutieName" column="dutie_name"></result>
</resultMap>
3.3 使用association处理映射关系
通过在映射文件配置resultMap标签中的子标签association实现多对一映射。
在MinisterMapper接口中声明方法getGeneralMinisterByDutie(@Param("ministerDutie") Integer ministerDutie),该方法的返回值类型为List集合,List集合中存储Minister类型的数据,采用@Param注解的方式获取参数。
//查询职称为武将的人员信息,实现多对一映射
List<Minister> getGeneralMinisterByDutie(@Param("ministerDutie") Integer ministerDutie);
在映射文件中实现Sql语句,采用resultMap自定义映射。通过resultMap的value值匹配自定义映射resultMap中id的value值。
<!-- List<Minister> getGeneralMinisterByDutie(@Param("ministerDutie") Integer ministerDutie);-->
<select id="getGeneralMinisterByDutie" resultMap="GeneralMinisterByDutie">
select *from t_minister where minister_dutie=#{ministerDutie}
</select>
对于自定义映射resultMap标签中的子标签association属性:
property:实体类的属性名 javaType:设置property对象对应的实体类类型
association标签中的子标签属性:
property:javaType实体类的属性名 column:javaType实体类对应表的字段名
<resultMap id="GeneralMinisterByDutie" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<association property="dutie" javaType="Dutie">
<id property="dutieId" column="dutie_id"></id>
<result property="dutieName" column="dutie_name"></result>
</association>
</resultMap>
完整的映射文件:
<!-- List<Minister> getGeneralMinisterByDutie(@Param("ministerDutie") Integer ministerDutie);-->
<select id="getGeneralMinisterByDutie" resultMap="GeneralMinisterByDutie">
select *from t_minister where minister_dutie=#{ministerDutie}
</select>
<resultMap id="GeneralMinisterByDutie" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<association property="dutie" javaType="Dutie">
<id property="dutieId" column="dutie_id"></id>
<result property="dutieName" column="dutie_name"></result>
</association>
</resultMap>
3.4 分步查询
目标:使用分步查询获取人员的信息,再通过人员的minister_dutie的属性值获取人员的部门信息。
分步查询的实质就是执行两条Sql语句,在MinisterMapper的映射文件中使用分步查询之前需要实现DutieMapper接口中部门信息的查询方法。
下面是实现DutieMapper接口中部门信息的查询方法。
在DutieMapper接口中声明getDutieByDutieId(@Param("dutieId") Integer dutieId)方法,该方法的返回值类型为Dutie类型,采用@Param注解的方式获取参数值。
//通过dutieId查询人员的部门信息,分步查询第二步
Dutie getDutieByDutieId(@Param("dutieId") Integer dutieId);
在对应的映射文件中实现Sql语句,采用resultMap自定义映射的方式指定结果类型。
<!-- Dutie getDutieByDutieId(@Param("dutieId") Integer dutieId);-->
<select id="getDutieByDutieId" resultMap="DutieByDutieId">
select *from t_dutie where dutie_id=#{dutieId}
</select>
<resultMap id="DutieByDutieId" type="Dutie" >
<id property="dutieId" column="dutie_id"></id>
<result property="dutieName" column="dutie_name"></result>
</resultMap>
下面是实现MinisterMapper接口中分步查询。
在MinisterMapper接口声明getMinisterByStep(@Param("dutieId") Integer dutieId)方法,方法的返回值为List集合,存储的数据类型为Minister类型,采用@Param注释的方法获取参数值。
//采用分步查询获取dutieId为3的人员信息,分步查询第一步
List<Minister> getMinisterByStep(@Param("dutieId") Integer dutieId);
在对应的映射文件中实现Sql语句,采用resultMap自定义映射。
<!-- Minister getMinisterByStep(@Param("dutieId") Integer dutieId);-->
<select id="getMinisterByStep" resultMap="MinisterByStep">
select *from t_minister where minister_dutie=#{dutieId}
</select>
<resultMap id="MinisterByStep" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<association property="dutie" select="com.review.mybaties.mapper.DutieMapper.getDutieByDutieId" column="minister_dutie">
</association>
</resultMap>
上述映射文件中association标签中的property="dutie"属性的value是Minister类的属性名,select的value定位分步查询第二步的方法位置,column的属性值是实体类Minister对应表的字段名minister_dutie,也是传给第二步查询参数的值。
3.4.1 延迟加载
分步查询的优点是可以实现延迟加载,如果要开启延迟加载需要在MyBatis的核心配置文件的settings的子标签setting的name属性设置为lazyLoadingEnabled,value值为true,默认值为false关闭延迟加载;设置lazyLoadingEnabled后,还需设置aggressiveLazyLoading开启按需加载,当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载,aggressiveLazyLoading的默认值为false开启按需加载。
<settings>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 开启按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
对于【3.4】的操作 ,如果输出的结果不包含dutie属性,则程序仅仅执行第一步,不会执行分步查询第二步。除非输出结果包含dutie属性,程序才会执行分步查询第二步。
值得注意的是不是所有的分步加载都需要延迟加载,对于不需要延迟加载的分布操作,可以在association标签中设置fetchType属性的值,value为eager时,为立即加载,不支持延迟加载;为lazy时可以延迟加载。
如下resultMap自定义映射,分步查询支持延迟加载。
<resultMap id="MinisterByStep" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
<association property="dutie"
fetchType="lazy" select="com.review.mybaties.mapper.DutieMapper.getDutieByDutieId" column="minister_dutie">
</association>
</resultMap>
4、一对多映射
4.1 前置工作
在Dutie类中添加一个private List<Minister> minister属性,添加对应的GET和SET方法,重写toString方法。
处理一对多的关系需要使用resultMap中的子标签collection,collection中的属性 ofType:设置collection标签所处理的集合属性中存储数据的类型。
4.2 级联方式处理映射关系
在DutieMapper接口中创建getAllMinisterByDutieId(@Param("dutieId") Integer dutieId)方法,方法的返回值类型是Dutie类型,采用@Param注解的方式获取参数。
//根据部门dutie_id查询该部门所有员工
Dutie getAllMinisterByDutieId(@Param("dutieId") Integer dutieId);
在映射文件中实现Sql语句,采用resultMap自定义映射。
<!-- Dutie getAllMinisterByDutieId(@Param("dutieId") Integer dutieId);-->
<select id="getAllMinisterByDutieId" resultMap="MinisterByDutieId">
select * from t_dutie d left join t_minister m on d.dutie_id=m.minister_dutie where d.dutie_id=#{dutieId}
</select>
<resultMap id="MinisterByDutieId" type="Dutie">
<id property="dutieId" column="dutie_id"></id>
<result property="dutieName" column="dutie_name"></result>
<collection property="minister" ofType="Minister" >
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="gender" column="gender"></result>
<result property="ministerDutie" column="minister_dutie"></result>
</collection>
</resultMap>
4.3 分步查询
目标:使用分步查询查询官职信息,人员信息。
分步查询的实质就是执行两条Sql语句,在DutieMapper的映射文件中使用分步查询之前需要实现MinisterMapper接口中人员信息的查询方法。
下面是实现MinisterMapper接口中人员信息查询方法。
//根据ministerDutie查询人员信息,分步查询第二步
List<Minister> getMinisterByMinisterDutie(@Param("ministerDutie") Integer ministerDutie);
在映射文件中实现Sql语句,采用resultMap自定义映射
<!-- List<Minister> getMinisterByMinisterDutie(@Param("ministerDutie") Integer ministerDutie);-->
<select id="getMinisterByMinisterDutie" resultMap="MinisterMaperr">
select *from t_minister where minister_dutie=#{ministerDutie}
</select>
<resultMap id="MinisterMaperr" type="Minister">
<id property="id" column="id"></id>
<result property="ministerName" column="minister_name"></result>
<result property="age" column="age"></result>
<result property="ministerDutie" column="minister_dutie"></result>
</resultMap>
下面在DutieMapper接口中声明getAllMinisterByDutieId(@Param("dutieId") Integer dutieId)方法。
//根据部门dutie_id查询该部门所有员工,分步查询第一步
Dutie getAllMinisterByDutieId(@Param("dutieId") Integer dutieId);
在映射文件中实现Sql语句,标签collection表示一个集合,因此需要使用ofType属性指定集合中存储的类型
<!-- Dutie getAllMinisterByStep(@Param("dutieId") Integer dutieId);-->
<select id="getAllMinisterByStep" resultMap="AllMinisterByStep">
select * from t_dutie where dutie_id=#{dutieId}
</select>
<resultMap id="AllMinisterByStep" type="Dutie">
<id property="dutieId" column="dutie_id"></id>
<result property="dutieName" column="dutie_name"></result>
<collection property="minister" select="com.review.mybaties.mapper.MinisterMapper.getMinisterByMinisterDutie" column="dutie_id">
</collection>
</resultMap>
4.3.1 延迟加载
参考本篇博客的【3.4.1】