這里寫目錄標題
- 一、準備工作
- 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);}