文章目录
- 搭建MyBatis框架(表格、配置文件,接口,实现类)
- 一、resultMap处理字段和属性的映射关系
- 1.1 问题:查询不一致的字段结果为null。
- 1.2 解决方法1:为字段起别名,保持和属性名一致
- 1.3 解决方法2:全局配置信息mapUnderscoreToCamelCase
- 1.4 解决方法3:自定义映射resultMap
- 二、多对一映射处理
- 2.1 方法1:级联方式处理映射关系
- 2.2 方法2:使用association处理映射关系
- 2.3 方法3:分步查询
- (1) 查询员工信息
- (2) 查询部门信息
- 三、一对多映射处理
- 3.1 方法1:collection(用来处理一对多的映射关系)
- 3.2 方法2:分步查询
- (1) 查询部门信息
- (2) 根据部门id查询部门中的所有员工
- 四、延迟加载
搭建MyBatis框架(表格、配置文件,接口,实现类)
- 创建两个员工表格t_emp和t_dept
- 在pojo包中创建实体类
Emp:
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
public Emp() {
}
public Emp(Integer eid, String empName, Integer age, String sex, String email, Dept dept) {
this.eid = eid;
this.empName = empName;
this.age = age;
this.sex = sex;
this.email = email;
this.dept = dept;
}
public Integer getEid() {
return eid;
}
public void setEid(Integer eid) {
this.eid = eid;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"eid=" + eid +
", empName='" + empName + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", email='" + email + '\'' +
", dept=" + dept +
'}';
}
}
Dept:
public class Dept {
private Integer did;
private String deptName;
public Dept() {
}
public Dept(Integer did, String deptName) {
this.did = did;
this.deptName = deptName;
}
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Dept{" +
"did=" + did +
", deptName='" + deptName + '\'' +
'}';
}
}
- 配置mybatis-config文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"></properties>
<typeAliases>
<package name="cn.dhu.mybatis.pojo"/>
</typeAliases>
<!--设置连接数据库的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="cn.dhu.mybatis.mapper"/>
</mappers>
</configuration>
- 创建mapper接口和映射文件(略)
一、resultMap处理字段和属性的映射关系
解决字段(数据库表格中emp_name)与实体类属性empName不一致的问题。
1.1 问题:查询不一致的字段结果为null。
[Emp{eid=1, empName='null', age=23, sex='男', email='12@qq.com'},
Emp{eid=2, empName='null', age=43, sex='女', email='13@qq.com'},
Emp{eid=3, empName='null', age=13, sex='男', email='14@qq.com'},
Emp{eid=4, empName='null', age=25, sex='女', email='32@qq.com'},
Emp{eid=5, empName='null', age=58, sex='男', email='42@qq.com'}]
1.2 解决方法1:为字段起别名,保持和属性名一致
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
select eid, emp_name empName,age ,sex, email from t_emp
</select>
1.3 解决方法2:全局配置信息mapUnderscoreToCamelCase
可以在MyBatis的核心配置文件中的
setting
标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。
在mybatis-config.xml文件中配置:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
1.4 解决方法3:自定义映射resultMap
- resultMap:设置自定义映射
- 属性:
- id:表示自定义映射的唯一标识(虚拟映射字段和属性)不能重复
- type:查询的数据要映射的实体类的类型
- 子标签:
- id:设置主键的映射关系
- result:设置普通字段的映射关系
- 子标签属性:
- property:设置映射关系中实体类中的属性名
- column:设置映射关系中表中的字段名
<resultMap id="empResultMap" type="emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>
二、多对一映射处理
2.1 方法1:级联方式处理映射关系
- mapper接口中(EmpMapper)
返回类型为Emp
//查询员工以及员工所对应的部门信息
Emp getEmpAndDept(@Param("eid")Integer eid);
- mapper映射文件中(EmpMapper.xml)
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<resultMap id="empAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
- test测试文件中(ResultMapTest)
//查询员工以及员工所对应的部门信息
@Test
public void testGetEmpAndDept(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDept(1);
System.out.println(emp);
}
2.2 方法2:使用association处理映射关系
- association:处理多对一的映射关系
- property:需要处理多对的映射关系的属性名(dept)
- javaType:该属性的类型(Dept)
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>
2.3 方法3:分步查询
(1) 查询员工信息
- mapper接口中(EmpMapper)
返回类型为Emp
//分步查询第一步:查询员工信息
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
- mapper映射文件中(EmpMapper.xml)
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept"
(根据sql语句唯一标识,确定第二步查询语句位置)
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
(第二步查询语句的条件)
column="did"></association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where eid = #{eid}
</select>
(2) 查询部门信息
- mapper接口中(DempMapper)
返回类型为Dept
//分步查询第二步:通过did查询员工对应的部门信息
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
- mapper映射文件中(DeptMapper.xml)
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
select * from t_dept where did = #{did}
</select>
(3)测试文件(ResultMapTest)
@Test
public void testGetEmpAndDeptByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(3);
System.out.println(emp);
}
三、一对多映射处理
3.1 方法1:collection(用来处理一对多的映射关系)
- collection:用来处理一对多的映射关系
- ofType:表示该属性对应的集合中存储的数据的类型(Emp)
- mapper接口中(EmpMapper)
返回类型为Emp
//查询部门信息及其对应的所有员工
Dept getDeptAndEmp(@Param("did") Integer did);
- mapper映射文件中(EmpMapper.xml)
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>
- test测试文件中(ResultMapTest)
//查询部门及其对应的所有员工
@Test
public void testGetDeptAndEmp(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getDeptAndEmp(1);
System.out.println(dept);
}
3.2 方法2:分步查询
(1) 查询部门信息
- mapper接口中(DempMapper)
返回类型为Dept
//分步查询第一步:查询部门信息
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
- mapper映射文件中(DeptMapper.xml)
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="cn.dhu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
select * from t_dept where did = #{did}
</select>
(2) 根据部门id查询部门中的所有员工
- mapper接口中(EmpMapper)
返回类型为List<Emp>
//分步查询第二步:根据部门id查询部门中的所有员工
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
- mapper映射文件中(EmpMapper.xml)
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
注意此处驼峰命名映射已开启-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>
(3)测试文件(ResultMapTest)
//分步查询部门及其对应的所有员工
@Test
public void testGetDeptAndEmpByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getDeptAndEmpByStepOne(1);
System.out.println(dept);
}
四、延迟加载
- 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
-
lazyLoadingEnabled
:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载 -
aggressiveLazyLoading
:当开启true
时,任何方法的调用都会加载该对象的所有属性。 否则false
,每个属性会按需加载,即用到的时候才会加载
因此就可以实现按需加载,获取的数据是什么,就只会执行相应的sql语句。此时可通过association和collection中的fetchType
属性设置当前的分步查询是否使用延迟加载,fetchType="lazy"
(延迟加载)fetchType="eager"
(立即加载)"
- 在mybatis-config文件中开启延迟加载
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
- 测试类
//分步查询部门及其对应的所有员工,延时加载测试
@Test
public void testGetDeptAndEmpByStepDelay(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getDeptAndEmpByStepOne(1);
System.out.println(dept.getDeptName());
System.out.println("========================");
System.out.println(dept.getEmps());
}
- 延迟加载的效果:
注:fetchType使用位置
<collection property="emps"
select="cn.dhu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"
fetchType="lazy"></collection>
本文主要参考:
【尚硅谷】2022版MyBatis教程(细致全面,快速上手)