新建Mybatis项目,搭建MyBatis框架过程不再赘述,参考前期博客:开始准备工作,此处只给出新内容
准备工作
创两个表,多对一关系(一个部门可以有多个员工),简单添加几条数据,如下:
t_dept 表,did主键自增 t_emp 表,eid主键自增 创建两个pojo类:
Emp.java
package com.mybatis.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
}
Dept.java
package com.mybatis.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString
public class Dept {
private Integer did;
private String deptName;
}
注意:此时,实体类中的部分属性和数据库表中的部分字段命名不一致,如表中字段是采用下划线(emp_name、dept_name),而实体类中采用的是驼峰命名法(empName、deptName)
1、resultMap处理字段和属性的映射关系
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
EmpMapper 接口
List<Emp> getAllEmp();
EmpMapper 映射
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>
resultMap:设置自定义映射,只在查询有用
-
属性:
- id:表示自定义映射的唯一标识
- type:查询的数据要映射的实体类的类型
-
子标签:
- id:设置主键的映射关系
- result:设置普通字段的映射关系
- association:设置多对一的映射关系
- collection:设置一对多的映射关系
- 属性:
- property:设置映射关系中实体类中的属性名
- column:设置映射关系中表中的字段名
测试方法
@Test
public void testGetAllEmp() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
mapper.getAllEmp().forEach(System.out::println);
}
运行结果
若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰),此时还可以通过以下两种方式处理字段名和实体类中的属性的映射关系
a>通过为字段起别名的方式,保证和实体类中的属性名保持一致,如下:
<select id="getAllEmp" resultType="Emp">
select eid,emp_name as empName,age,sex,email,did from t_emp
</select
此处为emp_name起别名为empName
b>在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,在查询表中数据时,自动将_类型的字段名转换为驼峰,如下,参考MyBatis核心配置文件:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
此处将字段名emp_name自动转换为empName
2、多对一映射处理
查询员工信息以及员工所对应的部门信息
在Emp.java 添加一行属性:
private Dept dept;
a>级联方式处理映射关系
EmpMapper 接口
Emp getEmpAndDept(@Param("eid") Integer eid);
EmpMapper 映射
<resultMap id="empAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<result property="dept.did" column="did" />
<result property="dept.deptName" column="dept_name" />
</resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
select * from t_emp join t_dept on t_emp.did=t_dept.did where t_emp.eid = #{eid}
</select>
测试方法
@Test
public void testGetEmpAndDept() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(mapper.getEmpAndDept(5));
}
运行结果
b>使用association处理映射关系
EmpMapper 映射
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<association property="dept" javaType="Dept">
<id property="did" column="did" />
<result property="deptName" column="dept_name" />
</association>
</resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp join t_dept on t_emp.did=t_dept.did where t_emp.eid = #{eid}
</select>
association:处理多对一映射关系,属性如下:
- property:需要处理多对的映射关系的属性名
- javaType:该属性的类型
运行结果同上
c>分步查询
EmpMapper 接口
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
EmpMapper 映射
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<association property="dept" select="com.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did" />
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where eid = #{eid}
</select>
association属性:
DeptMapper 接口
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
DeptMapper 映射
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from t_dept where did= #{did}
</select>
在MyBatis核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase为true,_自动转驼峰
测试方法
@Test
public void testGetEmpAndDeptByStep() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(mapper.getEmpAndDeptByStepOne(2));
}
运行结果
3、一对多映射处理
查询部门信息以及部门中的员工信息
在Dept.java 添加一行属性:
private List<Emp> emps;
a>使用collection处理映射关系
DeptMapper 接口
Dept getDeptAndEmp(@Param("did") Integer did);
DeptMapper 映射
<resultMap id="deptAndEmpResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dept_name"/>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
</collection>
</resultMap>
<select id="getDeptAndEmp" resultMap="deptAndEmpResultMap">
select * from t_dept join t_emp on t_dept.did=t_emp.did where t_dept.did=#{did}
</select>
collection:处理一对多映射关系,属性如下:
- ofType:表示该属性所对应的集合中存储数据的类型
测试方法
@Test
public void testGetDeptAndEmp() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
System.out.println(mapper.getDeptAndEmp(1));
}
运行结果
Dept(did=1, deptName=A, emps=[
Emp(eid=1, empName=张飞, age=36, sex=男, email=100@163.com, dept=null),
Emp(eid=4, empName=孙尚香, age=32, sex=女, email=103@sohu.com, dept=null)
])
b>分步查询
DeptMapper 接口
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
DeptMapper 映射
<resultMap id="deptAndEmpByStepResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dept_name"/>
<collection property="emps" select="com.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo" column="did"/>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap">
select * from t_dept where did= #{did}
</select>
EmpMapper 接口
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
EmpMapper 映射
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>
测试方法
@Test
public void testGetDeptAndEmpByStep() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
System.out.println(mapper.getDeptAndEmpByStepOne(1));
}
运行结果
分步查询的优点:可以实现延迟加载,但是必须在MyBatis核心配置文件中设置全局配置信息:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql;例如只查询部门名称:
System.out.println(mapper.getDeptAndEmpByStepOne(1).getDeptName());
-
未开启延迟加载 -
开启延迟加载
当开启了全局的延迟加载后,可以通过association和collection中的fetchType属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载,默认) | eager(立即加载)”,指定属性后,将在映射中忽略全局配置参数 lazyLoadingEnabled ,从而使用该属性的值。
注意:若没有开启全局的延迟加载,fetchType无论设置哪个值,都是立即加载!
|