四:MyBatis基于XML的详细使用——高级结果映射
Posted PoetryAndTheDistance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四:MyBatis基于XML的详细使用——高级结果映射相关的知识,希望对你有一定的参考价值。
目录
1、联合查询
emp.java
import java.time.LocalDate;
public class Emp {
private Integer id;
private String username;
private LocalDate createDate;
private deptId deptId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LocalDate getCreateDate() {
return createDate;
}
public void setCreateDate(LocalDate createDate) {
this.createDate = createDate;
}
public Integer getDeptId() {
return dept;
}
public void setDeptId(Integer deptId) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", username='" + username + '\\'' +
", createDate=" + createDate +
", deptId=" + deptId+
'}';
}
}
EmpMapper.xml
<!-- 实现表联结查询的方式: 可以映射: DTO -->
<resultMap id="QueryEmp_Map" type="QueryEmpDTO">
<id column="e_id" property="id"></id>
<result column="user_name" property="username"></result>
<result column="d_id" property="deptId"></result>
<result column="dept_name" property="deptName"></result>
</resultMap>
<select id="QueryEmp" resultMap="QueryEmp_Map">
select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
INNER JOIN dept t2 on t1.dept_id=t2.id
where t1.id=#{id}
</select>
<!-- 实现表联结查询的方式: 可以映射map -->
<resultMap id="QueryEmp_Map" type="map">
<id column="e_id" property="id"></id>
<result column="user_name" property="username"></result>
<result column="d_id" property="deptId"></result>
<result column="dept_name" property="deptName"></result>
</resultMap>
<select id="QueryEmp" resultMap="QueryEmp_Map">
select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
INNER JOIN dept t2 on t1.dept_id=t2.id
where t1.id=#{id}
</select>
QueryEmpDTO
public class QueryEmpDTO {
private String deptName;
private Integer deptId;
private Integer id;
private String username;
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "QueryEmpDTO{" +
"deptName='" + deptName + '\\'' +
", deptId=" + deptId +
", id=" + id +
", username='" + username + '\\'' +
'}';
}
}
Test
@Test
public void test01() {
try(SqlSession sqlSession = sqlSessionFactory.openSession()){
// Mybatis在getMapper就会给我们创建jdk动态代理
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
QueryEmpDTO dto = mapper.QueryEmp(4);
System.out.println(dto);
}
}
2、嵌套结果
2.1多对一
EmpMapper.xml
<!--嵌套结果 多 对 一 -->
<resultMap id="QueryEmp_Map2" type="Emp">
<id column="e_id" property="id"></id>
<result column="user_name" property="username"></result>
<!--
association 实现多对一中的 “一”
property 指定对象中的嵌套对象属性
-->
<association property="dept">
<id column="d_id" property="id"></id>
<id column="dept_name" property="deptName"></id>
</association>
</resultMap>
<select id="QueryEmp2" resultMap="QueryEmp_Map2">
select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
INNER JOIN dept t2 on t1.dept_id=t2.id
where t1.id=#{id}
</select>
2.2一对多
<!-- 嵌套结果: 一对多 查询部门及所有员工 -->
<resultMap id="SelectDeptAndEmpsMap" type="Dept">
<id column="d_id" property="id"></id>
<id column="dept_name" property="deptName"></id>
<!--
<collection 映射一对多中的 “多”
property 指定需要映射的“多”的属性,一般声明为List
ofType 需要指定list的类型
-->
<collection property="emps" ofType="Emp" >
<id column="e_id" property="id"></id>
<result column="user_name" property="username"></result>
<result column="create_date" property="createDate"></result>
</collection>
</resultMap>
<select id="SelectDeptAndEmps" resultMap="SelectDeptAndEmpsMap">
select t1.id as d_id,t1.dept_name,t2.id e_id,t2.user_name,t2.create_date from dept t1
LEFT JOIN emp t2 on t1.id=t2.dept_id
where t1.id=#{id}
</select>
Emp.java
import java.time.LocalDate;
/***
* @Author 徐庶 QQ:1092002729
* @Slogan 致敬大师,致敬未来的你
*/
public class Emp {
private Integer id;
private String username;
private LocalDate createDate;
private Dept dept;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LocalDate getCreateDate() {
return createDate;
}
public void setCreateDate(LocalDate createDate) {
this.createDate = createDate;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", username='" + username + '\\'' +
", createDate=" + createDate +
", dept=" + dept +
'}';
}
}
Dept.java:
public class Dept {
private Integer id;
private String deptName;
private List<Emp> emps;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", deptName='" + deptName + '\\'' +
", emps=" + emps +
'}';
}
}
EmpMapper.java:
public interface EmpMapper {
QueryEmpDTO QueryEmp(Integer id);
Emp QueryEmp2(Integer id);
Emp QueryEmp3(Integer id);
}
DeptMapper.java:
public interface DeptMapper {
//嵌套查询: 一对多 使用部门id查询员工
Dept SelectDeptAndEmps(Integer id);
// 嵌套查询(异步查询): 一对多 查询部门及所有员工
Dept SelectDeptAndEmps2(Integer id);
}
3、嵌套查询
在上述逻辑的查询中,是由我们自己来完成sql语句的关联查询的,那么,我们能让mybatis帮我们实现自动的关联查询吗?
3.1、多对一
EmpMapper.xml:
<!--嵌套查询(分步查询) 多 对 一
联合查询和分步查询区别: 性能区别不大
分部查询支持 懒加载(延迟加载)
需要设置懒加载,一定要使用嵌套查询的。
要启动懒加载可以在全局配置文件中设置 lazyLoadingEnabled=true
还可以单独为某个分步查询设置立即加载 <association fetchType="eager"
-->
<resultMap id="QueryEmp_Map3" type="Emp">
<id column="id" property="id"></id>
<result column="user_name" property="username"></result>
<!-- association 实现多对一中的 “一”
property 指定对象中的嵌套对象属性
column 指定将哪个字段传到分步查询中
select 指定分步查询的 命名空间+ID
以上3个属性是实现分步查询必须的属性
fetchType 可选, eager|lazy eager立即加载 lazy跟随全局配置文件中的lazyLoadingEnabled
-->
<association property="dept" column="dept_id" select="cn.tulingxueyuan.mapper.DeptMapper.SelectDept">
</association>
</resultMap>
<select id="QueryEmp3" resultMap="QueryEmp_Map3">
select * from emp where id=#{id}
</select>
DeptMapper.xml
<!-- 根据部门id查询部门-->
<select id="SelectDept" resultType="dept">
SELECT * FROM dept where id=#{id}
</select>
3.2、一对多
DeptMapper.xml
<!-- 嵌套查询(异步查询): 一对多 查询部门及所有员工 -->
<resultMap id="SelectDeptAndEmpsMap2" type="Dept">
<id column="d_id" property="id"></id>
<id column="dept_name" property="deptName"></id>
<!--
<collection 映射一对多中的 “多”
property 指定需要映射的“多”的属性,一般声明为List
ofType 需要指定list的类型
column 需要将当前查询的字段传递到异步查询的参数
select 指定异步查询
-->
<collection property="emps" ofType="Emp" column="id" select="cn.tulingxueyuan.mapper.EmpMapper.SelectEmpByDeptId" >
</collection>
</resultMap>
<select id="SelectDeptAndEmps2" resultMap="SelectDeptAndEmpsMap2">
SELECT * FROM dept where id=#{id}
</select>
EmpMapper.xml
<!-- 根据部门id所有员工 -->
<select id="SelectEmpByDeptId" resultType="emp">
select * from emp where dept_id=#{id}
</select>
Emp.java
public class Emp {
private Integer id;
private String username;
private LocalDate createDate;
private Dept dept;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LocalDate getCreateDate() {
return createDate;
}
public void setCreateDate(LocalDate createDate) {
this.createDate = createDate;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", username='" + username + '\\'' +
", createDate=" + createDate +
", dept=" + dept +
'}';
}
}
Dept.java:
public class Dept {
private Integer id;
private String deptName;
private List<Emp> emps;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", deptName='" + deptName + '\\'' +
", emps=" + emps +
'}';
}
}
EmpMapper.java:
public interface EmpMapper {
QueryEmpDTO QueryEmp(Integer id);
Emp QueryEmp2(Integer id);
Emp QueryEmp3(Integer id);
}
DeptMapper.java:
public interface DeptMapper {
//嵌套查询: 一对多 使用部门id查询员工
Dept SelectDeptAndEmps(Integer id);
// 嵌套查询(异步查询): 一对多 查询部门及所有员工
Dept SelectDeptAndEmps2(Integer id);
}
4、延迟查询
当我们在进行表关联的时候,有可能在查询结果的时候不需要关联对象的属性值,那么此时可以通过延迟加载来实现功能。在全局配置文件中添加如下属性
mybatis-config.xml
<!-- 开启延迟加载,所有分步查询都是懒加载 (默认是立即加载)-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--当开启式, 使用pojo中任意属性都会加载延迟查询 ,默认是false
<setting name="aggressiveLazyLoading" value="false"/>-->
<!--设置对象的哪些方法调用会加载延迟查询 默认:equals,clone,hashCode,toString-->
<setting name="lazyLoadTriggerMethods" value=""/>
如果设置了全局加载,但是希望在某一个sql语句查询的时候不使用延时策略,可以添加fetchType下属性:
<association property="dept" fetchType="eager" column="dept_id" select="cn.tulingxueyuan.mapper.DeptMapper.SelectDept">
</association>
5、总结
三种关联guan关系都有两种关联查询的方式,嵌套查询,嵌套结果
*Mybatis的yanc延迟加载配置
在全局配置文件中加入下面代码
<settings>
<setting name=”lazyLoadingEnabled” value=”true” />
<setting name=”aggressiveLazyLoading” value=”false”/>
</settings>
在映射文件中,元素和元素中都已默认配置了延迟加载属性,即默认属性fetchType=”lazy”(属性fetchType=”eager”表示立即加载),所以在配置文件中开启延迟加载后,无需在映射文件中再做配置
1.一对一
使用元素进行一对一关联映射非常简单,只需要参考如下两种示例配置即可
2.一对多
元素中,包含了一个子元素,MyBatis就是通过该元素来处理一对多关联关系的
子元素的属性大部分与元素相同,但其还包含一个特殊属性–ofType
ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型。
元素的使用也非常简单,同样可以参考如下两种示例进行配置,具体代码如下:
3.多对多
多对多的关联关系查询,同样可以使用前面介绍的元素进行处理(其用法和一对多关联关系查询语句用法基本相同
以上是关于四:MyBatis基于XML的详细使用——高级结果映射的主要内容,如果未能解决你的问题,请参考以下文章
Maven 项目使用mybatis的环境搭建-基于xml形式实现查询所有的功能