这里写目录标题
- 一、准备工作
- 1、新建maven工程
- 2、准备两张表
- 3、建立mapper、pojo、映射文件
- mapper接口
- pojo
- xxxMapper.xml
- 二、resultMap处理字段和属性的映射关系
- 1、用起别名的方式保证字段名与属性名一致
- 2、逐一设置resultMap映射关系
- 3、配置mapUnderscoreToCamelCase
- 三、多对一映射关系
- 1、级联方式处理映射关系
- 2、使用association处理映射关系
- 3、分布查询
- 3.1、查询员工信息
- 3.2、根据员工所对应的部门id查询部门信息
- 延迟加载
- 四、一对多映射关系
- 1、collection
- 2、分步查询
- 1)查询部门信息
- 2)根据部门id查询部门中所有员工
- 3)测试类
一、准备工作
1、新建maven工程
新建一个maven工程,具体pom.xml文件以及数据库连接配置文件可以参考之前的笔记。
2、准备两张表
- 部门员工表
CREATE TABLE `t_emp` (`eid` int(11) NOT NULL AUTO_INCREMENT,`emp_name` varchar(45) DEFAULT NULL,`age` int(11) DEFAULT NULL,`sex` char(1) DEFAULT NULL,`email` varchar(45) DEFAULT NULL,`did` int(11) DEFAULT NULL,PRIMARY KEY (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='部门员工表';
- 部门机构表
CREATE TABLE `t_dept` (`did` int(11) NOT NULL AUTO_INCREMENT,`dept_name` varchar(45) DEFAULT NULL,PRIMARY KEY (`did`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='部门机构表';
每个表中添加相关参数:
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(1, 'Apple', 22, '女', '123456@qq.com', 1);
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(2, 'Bela', 33, '女', '123456@qq.com', 1);
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(3, 'Cherry', 21, '女', '123456@qq.com', 2);
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(4, 'David', 55, '男', '123456@qq.com', 2);
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(5, 'Eve', 25, '男', '123456@qq.com', 3);
INSERT INTO demo.t_emp (eid, emp_name, age, sex, email, did) VALUES(6, 'Feman', 34, '男', '123456@qq.com', 3);INSERT INTO demo.t_dept (did, dept_name) VALUES(1, '财务部');
INSERT INTO demo.t_dept (did, dept_name) VALUES(2, '仓储部');
INSERT INTO demo.t_dept (did, dept_name) VALUES(3, '技术部');
3、建立mapper、pojo、映射文件
mapper接口
public interface EmpMapper {
}
public interface DeptMapper {
}
pojo
Dept pojo:
public class Dept {private Integer did;private String deptName;@Overridepublic String toString() {return "Dept{" +"did=" + did +", 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;}public Dept() {}public Dept(Integer did, String deptName) {this.did = did;this.deptName = deptName;}}
Emp pojo :
public class Emp {private Integer eid;private String empName;private Integer age;private String sex;private String email;public Emp() {}public Emp(Integer eid, String empName, Integer age, String sex, String email) {this.eid = eid;this.empName = empName;this.age = age;this.sex = sex;this.email = email;}@Overridepublic String toString() {return "Emp{" +"eid=" + eid +", empName='" + empName + '\'' +", age=" + age +", sex='" + sex + '\'' +", email='" + email + '\'' +'}';}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;}}
xxxMapper.xml
DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.demo.mybatis.mapper.DeptMapper"></mapper>
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.demo.mybatis.mapper.EmpMapper"></mapper>
二、resultMap处理字段和属性的映射关系
若字段名和实体类中的属性名不一致,但是数据库字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。
这时候可以通过两种方式处理字段名和实体类中的属性的映射关系:
- 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
- 逐一设置resultMap映射关系
- 可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转为驼峰。
1、用起别名的方式保证字段名与属性名一致
和sql中一样,用字段名 属性名 如(emp_name empName)来使二者一致。
在mybatic-config.xml文件中添加别名配置:
<typeAliases><typeAlias type="cn.demo.mybatis.pojo.Emp" alias="Emp"></typeAlias></typeAliases>
<!-- List<Emp> getAllEmp();--><select id="getAllEmp" resultType="Emp">select eid, emp_name empName, age, sex, email from t_emp</select>
2、逐一设置resultMap映射关系
在resultMap中,一一对应的设置属性名—>字段名,再在select标签中添加resultMap=“对应resultMap的id”。
<resultMap id="empResultMap" type="cn.demo.mybatis.pojo.Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result></resultMap><select id="getAllDept" resultMap="empResultMap">select * from t_dept</select>
resultMap设置自定义映射关系:
+ id:唯一标识
+ type:映射的实体类型
子标签:
+ id:设置主键的映射关系
+ result:设置其他的映射关系
+ property:设置映射关系中的属性名,即Java实体类类型的属性
+ column:设置映射关系中的字段名,必须是sql语句查询出来的字段名
3、配置mapUnderscoreToCamelCase
在全局配置文件mybatis-config.xml中,加入如下属性配置信息:
<configuration><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>
这里设置MyBatis的全局配置,将下划线自动映射成驼峰,比如emp_name -> empName。
注意:settings标签要放在properties后面,否则会报错。
三、多对一映射关系
需要查询一对多,多对一的关系,需要在“一”的pojo中加入多的List<>属性,在“多”的pojo中加入“一”。
也就是说,在Dept类中,需要加入 private List emps; ,在Emp类中,要加入 private Dept dept 。然后给他们各自添加get、set方法,重写构造器和toString()。
1、级联方式处理映射关系
EmpMapper.xml中:
<!-- 多对一映射关系,方式一:级联属性赋值--><resultMap id="getEmpAndDeptResultMapOne" 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="getEmpAndDeptResultMapOne">select * from t_emp left join t_depton t_emp.eid = t_dept.did WHERE t_emp.eid = #{eid}</select>
EmpMapper类中
public interface EmpMapper {/*** 查询员工及其所对应的部门信息*/Emp getEmpAndDept(@Param("eid") Integer eid);
}
测试类中:
@Testpublic void testGetEmpAndDept(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp empAndDept = mapper.getEmpAndDept(3);System.out.println(empAndDept);}
2、使用association处理映射关系
当一个对象包含一个关联对象时(例如:一个员工emp对应一个部门dept),可以使用映射一对一关系。
EmpMapper.xml:
<resultMap id="empDeptMap" type="Emp"><id column="eid" property="eid"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="sex" property="sex"></result><result property="email" column="email"></result><association property="dept" javaType="Dept"><id column="did" property="did"></id><result column="dept_name" property="deptName"></result></association></resultMap><!--Emp getEmpAndDeptByEid(@Param("eid") int eid);--><select id="getEmpAndDeptByEid" resultMap="empDeptMap">select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did = dept.did where emp.eid = #{eid}</select>
association标签:
- property:映射实体类属性名
- javaType:映射java类型
- column:映射数据库字段名
- jdbcType:映射数据库类型
3、分布查询
3.1、查询员工信息
EmpMapper.xml
<resultMap id="getEmpAndDeptByStepResultMap" 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="did" column="did"></result><association property="dept"select="cn.demo.mybatis.mapper.DeptMapper.getDeptByStep"column="did"fetchType="eager"></association></resultMap><!-- Emp getEmpByStep(@Param("eid") int eid);--><select id="getEmpByStep" resultMap="getEmpAndDeptByStepResultMap">select * from t_emp where eid = #{eid}</select>
- select:设置了分布查询的sql唯一标识(xml的namespace.SQLId或mapper接口的全类名.方法名)
- column:分步查询的条件
- fetchType:通过该属性手动控制延迟加载的效果;lazy表示延迟加载,eager表示立即加载
3.2、根据员工所对应的部门id查询部门信息
DeptMapper.xml:
<!-- Dept getEmpAndDeptByStepTwo(Integer did);--><!-- 分步查询可以实现懒加载--><select id="getDeptByStep" resultType="Dept">select * from t_dept where did = #{did}</select>
延迟加载
分布查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。
- aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则每个属性都会按需加载。
lazyLoadingEnabled是控制是否开启懒加载的,而aggressiveLazyLoading是控制关联对象是如何进行懒加载的,比如控制当对关联对象任何的调用都会完全加载所有属性,还是只是按需加载对应属性。
<settings><!--开启延迟加载--><setting name="lazyLoadingEnabled" value="true"/>
</settings>
特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态
此时就可以实现按需求加载,获取的数据是什么,就会执行相应的sql。此时可通过association和 collection中的fetchType属性设置当前的分布查询是否使用延迟加载,fetchType=“lazy(延迟加 载)|eager(立即加载)”。
通过fetchType参数,可以手动控制延迟加载或立即加载,否则根据全局配置的属性决定是延迟加载还是立即加载。
@Testpublic void testGetEmpByStep() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp empAndDept = mapper.getEmpByStep(1);//先打印出emp的元素System.out.println(empAndDept.getEmpName());System.out.println("=====================");//再打印出deptSystem.out.println(empAndDept.getDept());}
当延迟开关打开时候,加载如下:
当延迟开关关闭时候,加载如下:
四、一对多映射关系
根据部门id查找部门以及部门中的员工信息。
1、collection
DeptMapper接口:
/*** 获取部门以及部门中所有的员工信息*/Dept getDeptAndEmp(@Param("did") Integer did);
DeptMapper.xml:
<resultMap id="deptAndEmpResultMap" type="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result><!--collection:处理一对多的映射关系ofType:表示该属性对应的集合中存储数据的类型--><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>
测试类
@Testpublic void testGetDeptAndEmp(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmp(1);System.out.println(dept);}
注意:
这里要在Dept类中,要加入private List emps;
2、分步查询
1)查询部门信息
Dept getDeptAndEmoByStepOne(@Param("did") Integer did)
<!-- 分步查询-->!-- 分步查询--><resultMap id="deptAndEmoByStepOneMap" type="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result><collection property="emps"select="cn.demo.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"column="did"></collection></resultMap><!-- Dept getDeptAndEmoByStepOne(@Param("did") Integer did);--><select id="getDeptAndEmoByStepOne" resultMap="deptAndEmoByStepOneMap">select * from t_dept where did = #{did}</select>
2)根据部门id查询部门中所有员工
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!-- List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);--><select id="getDeptAndEmpByStepTwo" resultType="Emp">select * from t_emp where did = #{did}</select>
3)测试类
@Testpublic void testGetDeptAndEmpBySteps() throws IOException {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmoByStepOne(2);System.out.println(dept.getDeptName());System.out.println("-----****************======分割线=======-----****************");System.out.println(dept);}