MyBatis框架關(guān)聯(lián)映射實(shí)例詳解
關(guān)系映射
1. 關(guān)聯(lián)映射概述
在關(guān)系型數(shù)據(jù)庫(kù)中,多表之間存在著三種關(guān)聯(lián)關(guān)系,分別為一對(duì)一,一對(duì)多和多對(duì)多,如圖
- 一對(duì)一的關(guān)系:就是在本類中定義對(duì)方類型的對(duì)象,如A類中定義B類類型的屬性b,B類中定義A類類型的屬性a。
- 一對(duì)多的關(guān)系:就是一個(gè)A類類型對(duì)應(yīng)多個(gè)B類類型的情況,需要在A類中以集合的方式引入B類類型的對(duì)象,在B類中定義A類類型的屬性a。
- 多對(duì)多的關(guān)系:在A類中定義B類類型的集合,在B類中定義A類類型的集合。
2. 環(huán)境搭建
創(chuàng)建t_emp表
t_dept表
實(shí)體類Dept
package com.atguigu.mybatis.pojo; import java.util.List; public class Dept { private Integer deptId; private String deptName; private List<Emp> emps; public Dept() { } public Dept(Integer deptId, String deptName) { this.deptId = deptId; this.deptName = deptName; } public Integer getDeptId() { return deptId; } public void setDeptId(Integer deptId) { this.deptId = deptId; } 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{" + "deptId=" + deptId + ", deptName='" + deptName + '\'' + ", emps=" + emps + '}'; } }
實(shí)體類Emp
package com.atguigu.mybatis.pojo; public class Emp { private Integer empId; private String empName; private Integer age; private String gender; private Dept dept; public Emp() { } public Emp(Integer empId, String empName, Integer age, String gender) { this.empId = empId; this.empName = empName; this.age = age; this.gender = gender; } public Integer getEmpId() { return empId; } public void setEmpId(Integer empId) { this.empId = empId; } 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 getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Emp{" + "empId=" + empId + ", empName='" + empName + '\'' + ", age=" + age + ", gender='" + gender + '\'' + ", dept=" + dept + '}'; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } }
3.處理字段名和屬性名不一致的情況
SQL語(yǔ)句
接口:
public interface EmpMapper { Emp getEmpById(@Param("empId") Integer empId); }
測(cè)試方法:
public void test(){ SqlSessionUtils sqlSessionUtils = new SqlSessionUtils(); SqlSession sqlSession = sqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empById = mapper.getEmpById(1); System.out.println(empById.toString()); }
執(zhí)行測(cè)試方法后會(huì)得到如下結(jié)果:
可以看到,我們的SQl語(yǔ)句并沒有問題,但為什么查詢出的結(jié)果會(huì)有NUll出現(xiàn)呢,這就是因?yàn)槲覀兊?strong>數(shù)據(jù)庫(kù)中的字段名于Emp
實(shí)體類的屬性名不一致,因此出現(xiàn)了無(wú)法對(duì)應(yīng)的情況。
解決辦法:
1.可以通過為字段起別名的方式,保證和實(shí)體類中的屬性名保持一致
select emp_id empId,emp_name empName,age,gender from t_emp where emp_id = #{empId};
再次執(zhí)行嘗試:
2.可以在MyBatis的核心配置文件中設(shè)置一個(gè)全局配置信息mapUnderscoreToCamelCase,
此屬性可以在查詢表中數(shù)據(jù)時(shí),自動(dòng)將_類型的字段名,即下劃線轉(zhuǎn)換為駝峰
舉個(gè)栗子:
例如:字段名user_id
,設(shè)置了mapUnderscoreToCamelCase
,此時(shí)字段名就會(huì)轉(zhuǎn)換為userId
<resultMap id="empResultMap" type="Emp"> <id property="empId" column="emp_id"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="gender" column="gender"></result> </resultMap> <select id="getEmpById" resultMap="empResultMap"> select * from t_emp where emp_id = #{empId}; </select>
4. 處理一對(duì)一映射
調(diào)節(jié)數(shù)據(jù)庫(kù)字段與實(shí)體類的屬性對(duì)應(yīng)需要標(biāo)簽resultMap
,如上文那個(gè)簡(jiǎn)單的查詢例子就可以這樣寫:
<resultMap id="empResultMap" type="Emp"> <id property="empId" column="emp_id"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="gender" column="gender"></result> </resultMap> <select id="getEmpById" resultMap="empResultMap"> select * from t_emp where emp_id = #{empId}; </select>
屬性:
- id:表示自定義映射的唯一標(biāo)識(shí)
- type:查詢的數(shù)據(jù)要映射的實(shí)體類的類型
子標(biāo)簽:
- id:設(shè)置主鍵的映射關(guān)系
- result:設(shè)置普通字段的映射關(guān)系
- association :設(shè)置多對(duì)一的映射關(guān)系
- collection:設(shè)置一對(duì)多的映射關(guān)系
屬性:
- property:設(shè)置映射關(guān)系中實(shí)體類中的屬性名
- column:設(shè)置映射關(guān)系中表中的字段名
5. 處理多對(duì)一映射
5.1 級(jí)聯(lián)方式處理
<resultMap id="empAndDeptResultMap" type="Emp"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <!--部門中的字段dept_id與Emp實(shí)體類中的屬性dept中的deptId相對(duì)應(yīng) --> <!--部門中的字段dept_name與Emp實(shí)體類中的屬性dept中的deptName相對(duì)應(yīng) --> <result column="dept_id" property="dept.deptId"></result> <result column="dept_name" property="dept.deptName"></result> </resultMap> <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap"> SELECT t_emp.*,t_dept.* FROM t_emp LEFT JOIN t_dept ON t_emp.dept_id=t_dept.dept_id where t_emp.emp_id=#{empId} </select>
接口:
測(cè)試方法:
public void test(){ SqlSessionUtils sqlSessionUtils = new SqlSessionUtils(); SqlSession sqlSession = sqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empAndDeptById = mapper.getEmpAndDeptById(1); System.out.println(empAndDeptById); }
查詢結(jié)果:
5.2 使用association處理映射關(guān)系
<resultMap id="empAndDeptResultMap" type="Emp"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <association property="dept" javaType="Dept"> <id column="dept_id" property="deptId"></id> <result column="dept_name" property="deptName"></result> </association> </resultMap>
5.3 分步查詢
第一步:查詢員工信息
<resultMap id="empAndDeptByStepResultMap" type="Emp"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getDeptByStep" column="dept_id"> </association> </resultMap> <select id="getEmpAndDeptByStep" resultMap="empAndDeptByStepResultMap"> select * from t_emp where emp_id=#{empId}; </select>
注意:
select:設(shè)置分步查詢,查詢某個(gè)屬性的值的sql的標(biāo)識(shí)(namespace.sqlid)
column:將sql以及查詢結(jié)果中的某個(gè)字段設(shè)置為分步查詢的條件
第二步:根據(jù)員工所對(duì)應(yīng)的部門 id 查詢部門信息
<select id="getDeptByStep" resultType="com.atguigu.mybatis.pojo.Dept"> select * from t_dept where dept_id=#{deptId}; </select>
測(cè)試方法:
public void test(){ SqlSessionUtils sqlSessionUtils = new SqlSessionUtils(); SqlSession sqlSession = sqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empAndDeptByStep = mapper.getEmpAndDeptByStep(1); System.out.println(empAndDeptByStep); }
執(zhí)行結(jié)果:
分步查詢的優(yōu)點(diǎn):可以實(shí)現(xiàn)延遲加載
但是必須在核心配置文件中設(shè)置全局配置信息:
lazyLoadingEnabled
:延遲加載的全局開關(guān)。當(dāng)開啟時(shí),所有關(guān)聯(lián)對(duì)象都會(huì)延遲加載aggressiveLazyLoading
:當(dāng)開啟時(shí),任何方法的調(diào)用都會(huì)加載該對(duì)象的所有屬性。否則,每個(gè)屬性會(huì)按需加載- 此時(shí)就可以實(shí)現(xiàn)按需加載,獲取的數(shù)據(jù)是什么,就只會(huì)執(zhí)行相應(yīng)的 sql 。此時(shí)可通 association和 collection 中的
fetchType
屬性設(shè)置當(dāng)前的分步查詢是否使用延遲加載, fetchType=“lazy(延遲加載) | eager(立即加載)”
6. 處理一對(duì)多查詢
接口:
使用collection
處理
- collection :設(shè)置一對(duì)多的映射關(guān)系
- ofType :設(shè)置 collection 標(biāo)簽所處理的集合屬性中存儲(chǔ)數(shù)據(jù)的類型
<resultMap id="DeptAndEmpByDeptIdResultMap" type="Dept"> <id column="dept_id" property="deptId"></id> <result column="dept_name" property="deptName"></result> <collection property="emps" ofType="Emp"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> </collection> </resultMap> <select id="getDeptAndEmpByDeptId" resultMap="DeptAndEmpByDeptIdResultMap"> SELECT t_emp.*,t_dept.* FROM t_dept LEFT JOIN t_emp ON t_emp.dept_id=t_dept.dept_id WHERE t_dept.dept_id=#{deptId} </select>
測(cè)試:
public void test4(){ SqlSessionUtils sqlSessionUtils = new SqlSessionUtils(); SqlSession sqlSession = sqlSessionUtils.getSqlSession(); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept deptAndEmpByDeptId = mapper.getDeptAndEmpByDeptId(1); System.out.println(deptAndEmpByDeptId); }
執(zhí)行結(jié)果:
7. 小結(jié)
關(guān)系映射主要處理復(fù)雜的SQl查詢,如子查詢,多表聯(lián)查等復(fù)雜查詢,應(yīng)用此種需求時(shí)可以考慮使用。
到此這篇關(guān)于MyBatis框架關(guān)聯(lián)映射的文章就介紹到這了,更多相關(guān)MyBatis關(guān)聯(lián)映射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Mybatis關(guān)聯(lián)映射舉例詳解
- MyBatis框架關(guān)聯(lián)映射實(shí)例詳解
- Mybatis實(shí)現(xiàn)關(guān)聯(lián)關(guān)系映射的方法示例
- MyBatis多對(duì)多關(guān)聯(lián)映射創(chuàng)建示例
- Mybatis一對(duì)多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析
- mybatis實(shí)現(xiàn)一對(duì)一關(guān)聯(lián)映射實(shí)例代碼
- 深入淺出MyBatis中映射文件和實(shí)體類的關(guān)聯(lián)性
相關(guān)文章
使用java實(shí)現(xiàn)http多線程斷點(diǎn)下載文件(一)
Java 多線程斷點(diǎn)下載文件基本原理:利用URLConnection獲取要下載文件的長(zhǎng)度、頭部等相關(guān)信息,并設(shè)置響應(yīng)的頭部信息,本文將詳細(xì)介紹,需要了解更多的朋友可以參考下2012-12-12Java判斷一個(gè)實(shí)體是不是空的簡(jiǎn)單方法
這篇文章主要給大家介紹了關(guān)于Java判斷一個(gè)實(shí)體是不是空的簡(jiǎn)單方法,實(shí)際項(xiàng)目中我們會(huì)有很多地方需要判空校驗(yàn),文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下2023-07-07不調(diào)用方法實(shí)現(xiàn)hutool導(dǎo)出excel圖片示例詳解
這篇文章主要為大家介紹了不調(diào)用方法實(shí)現(xiàn)hutool導(dǎo)出excel圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08IDEA調(diào)試小技巧之Evaluate調(diào)試工具詳解
這篇文章主要介紹了IDEA調(diào)試小技巧之Evaluate調(diào)試工具,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09使用Springboot打成jar包thymeleaf的問題
這篇文章主要介紹了使用Springboot打成jar包thymeleaf的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11