Mybatis查詢語(yǔ)句結(jié)果集的總結(jié)大全
簡(jiǎn)單查詢-resultType
數(shù)據(jù)準(zhǔn)備
字段 | 注釋 |
---|---|
SNO | 學(xué)號(hào) |
SNAME | 學(xué)生名字 |
SSEX | 性別 |
SBIRITHDAY | 生日 |
CLASS | 班級(jí) |
<!--建表語(yǔ)句:--> create table TEST.STUDENT ( SNO varchar(3) not null, SNAME varchar(4) not null, SSEX varchar(2) not null, SBIRTHDAY datetime null, CLASS varchar(5) null )
<!--Bean 文件--> public class Student { private String SNO; private String SNAME; private String SSEX; private Date SBIRTHDAY; private String CLASS; <!--get 和 set 方法--> ... }
例子
按照返回?cái)?shù)據(jù)類型大致分為基礎(chǔ)數(shù)據(jù)類型,JavaBean 和 Map。其中雖然返回的結(jié)果行數(shù)有單條也有多條,對(duì)應(yīng)的接口返回類型是集合或者單個(gè)對(duì)象,但是在 xml 映射文件中,resultType 的值是相同的。
1、指定字段-基礎(chǔ)數(shù)據(jù)類型
接口類:
<!--單條結(jié)果集--> String querySingleStudent(); <!--多條結(jié)果集--> List<String> queryAllStudent();
Mapper 文件:
<!--單條結(jié)果集--> <select id="querySingleStudent" resultType="string"> SELECT SNAME FROM TEST.STUDENT LIMIT 1 </select> <!--多條結(jié)果集--> <select id="queryAllStudent" resultType="string"> SELECT SNAME FROM TEST.STUDENT </select>
2、Map,一般為 hashMap
接口類:
<!--單條結(jié)果集--> Map<String, Object> queryStudentMap(); <!--多條結(jié)果集--> List<Map<String, Object>> queryAllStudentMap(); 復(fù)制代碼Mapper 文件: <!--單條結(jié)果集--> <select id="queryStudentMap" resultType="hashmap"> SELECT SNAME FROM TEST.STUDENT LIMIT 1 </select> <!--多條結(jié)果集--> <select id="queryAllStudentMap" resultType="hashmap"> SELECT SNAME FROM TEST.STUDENT </select>
其中:
- hashmap 為簡(jiǎn)寫,也可以使用 java.util.HashMap 全稱
- 默認(rèn)情況下,結(jié)果集中值為 null 時(shí), 不會(huì)增加映射對(duì)象的 setter 方法, (map 對(duì)象時(shí)為 put)。該行為可以在 mybatis-config.xml 配置文件中設(shè)置
<setting name="callSettersOnNulls" value="true"/> 覆蓋默認(rèn)設(shè)定。
3、JavaBean
接口類:
<!--單條結(jié)果集--> Student querySingleStudentBean(); <!--多條結(jié)果集--> List<Student> queryAllStudentBean();
Mapper 文件:
<!--單條結(jié)果集--> <select id="queryStudentMap" resultType="student"> SELECT SNAME FROM TEST.STUDENT LIMIT 1 </select> <!--多條結(jié)果集--> <select id="queryAllStudentMap" resultType="student"> SELECT SNAME FROM TEST.STUDENT </select>
resultType="student" 為 Student.java 的別名,也可以是全限定名。別名在 mybatis-config.xml 配置文件中設(shè)置:
<typeAliases> <typeAlias type="com.bean.Student" alias="student"/> ... </typeAliases>
但是如果 JavaBean 文件很多,不想一個(gè)個(gè)指定,也可以使用 package 標(biāo)簽 設(shè)置mybatis自動(dòng)掃描,別名即為類名的小寫。
<typeAliases> <package name="包名"/> </typeAliases>
復(fù)雜查詢 resultMap
對(duì)于一般的查詢語(yǔ)句,resultType 足夠了。對(duì)于多表查詢等情況,就要請(qǐng)出 resultMap 了。
數(shù)據(jù)庫(kù)字段和 java 數(shù)據(jù)類型映射關(guān)系
數(shù)據(jù)庫(kù)字段類型 jdbcType 和 java 數(shù)據(jù)類型 并不是一一對(duì)應(yīng)的關(guān)系,而且不同數(shù)據(jù)庫(kù)類型也不盡相同。而 mybatis 將 TypeHandler 作為兩者之間的映射關(guān)系。大部分情況下都是沒(méi)有問(wèn)題的,但是并非能覆蓋所有的情況,特殊情況下可以使用 resultMap 自定義這種映射關(guān)系。
舉個(gè)例子,數(shù)據(jù)庫(kù) LongVarchar 字段類型對(duì)應(yīng) java 中的 String 類型。但是在 DB2 數(shù)據(jù)庫(kù)中,查詢的 LongVarchar 類型的字段,在 mybatis 中被識(shí)別成 jdbcType 為 BLOB。有兩種解決方法,第一種是在 SQL 中對(duì)該字段使用 CAST 轉(zhuǎn)換為 VARCHAR(長(zhǎng)度)類型。另一種是使用 resultMap:
<resultMap id="resultMapDemo" type="" autoMapping="true"> <result property="" column="" jdbcType="VARCHAR" /> </resultMap> <select id="demoID" resultMap="resultMapDemo"> ... <select>
1、<select>標(biāo)簽中使用 resultMap 指定返回集合。注意 resultMap 和 resultType 不能同時(shí)使用
2、<resultMap> 標(biāo)簽
- id 和 select 標(biāo)簽指定映射關(guān)系
- type 和 resultType 一樣為返回類型的全限定名或者別名
- autoMapping 自動(dòng)映射關(guān)系,在這里目的只是修改一個(gè)字段,其他自動(dòng)采用自動(dòng)完成映射關(guān)系
3、<result> 標(biāo)簽
- property 為 java 變量名
- column 為數(shù)據(jù)庫(kù)字段名
- jdbcType 這里指定為 VARCHAR
id
字段的映射關(guān)系的標(biāo)簽即有,也有,在 mybatis 文檔中指出不使用id,會(huì)造成性能下降,因此將主鍵字段使用 id 標(biāo)簽是推薦的做法。但是如果不存在主鍵呢,當(dāng)你在 ResultMap 只提供了部分字段而不是全部字段,即使使用了 autoMapping 屬性,那么 mybatis 會(huì)按照你提供的字段名進(jìn)行去重。那么在使用 resultMap 的時(shí)候,最優(yōu)選擇是:
- 如果表存在主鍵,就使用id標(biāo)簽指定
- 如果表不存在主鍵,要么不配置字段的映射關(guān)系,使用 autoMapping 屬性自動(dòng)映射;或者不使用 autoMapping 將所有字段羅列。
多表關(guān)聯(lián)查詢
在 resultType 的例子中都只涉及到一張表,如果涉及多張表關(guān)聯(lián)查詢呢。我們可以簡(jiǎn)單的將所有列映射到 hashmap 的鍵值上。
但是 HashMap 不是一個(gè)很好的領(lǐng)域模型。 你的程序更可能會(huì)使用 JavaBean 或 POJO(Plain Old Java Objects,普通 Java 對(duì)象)作為領(lǐng)域模型。
因此這里均采用 JavaBean 作為領(lǐng)域模型。增加一個(gè)成績(jī)表 Score
字段 | 注釋 |
---|---|
SNO | 學(xué)號(hào) |
CNO | 課程編號(hào) |
DEGREE | 成績(jī) |
<!--建表語(yǔ)句--> create table SCORE ( SNO varchar(3) not null, CNO varchar(5) not null, DEGREE decimal(10, 1) not null )
<!--Bean 文件--> public class Score { private String SNO; private String CNO; private Double DEGREE; <!--get 和 set 方法--> ... }
一對(duì)一關(guān)系
這里的一對(duì)多關(guān)系是兩個(gè)表字段一一對(duì)應(yīng),一個(gè)學(xué)生的某門課的成績(jī)是唯一確定的。 在一一對(duì)應(yīng)的情況下要在 resultMap 中使用 標(biāo)簽。
在 Student.java 中增加字段 Score
<!--Student.java--> private Score score; public Score getScore() { return score; } public void setScore(Score score) { this.score = score; }
有兩種使用情況,第一種為嵌套查詢,即前一個(gè) SQL 查詢結(jié)果集中的字段作為參數(shù)傳遞給下一個(gè) SQL。第二種情況為嵌套結(jié)果集,即兩個(gè)表做關(guān)聯(lián)查詢,將結(jié)果集映射到多個(gè) JavaBean 文件。
嵌套查詢
<resultMap id="allstudentResultMap" type="student"> <!--指定第二個(gè) SELECT 語(yǔ)句,和傳遞的字段--> <association property="score" column="sno" select="queryScore" /> </resultMap> <!--第一個(gè) SQL --> <select id="queryAllStudent" resultMap="allstudentResultMap"> select SNO,SNAME from test.STUDENT </select> <!--第二個(gè) SQL--> <select id="queryScore" resultType="score"> select degree from test.SCORE where sno = #{sno} </select>
在標(biāo)簽中
- property 指向了 Student.java 中新增的 score 字段。
- column 指定了作為參數(shù)傳遞給下一個(gè)查詢SQL的字段,需要注意的是對(duì)于傳遞單個(gè)字段的情況,mybatis 只是簡(jiǎn)單的將 #{參數(shù)} 替換為占位符 ?, 然后執(zhí)行 resultSet.getString(columnName),沒(méi)有進(jìn)行參數(shù)匹配,因此第二個(gè) SQL 中 #{} 中寫任何字符都可以;如果需要傳遞多個(gè)字段,使用 column = " {prop1=col1,prop2=col2} ",這種情況下會(huì)以參數(shù)對(duì)象的形式來(lái)傳遞。
- select 指定了下一個(gè) SELECT 語(yǔ)句
另外需要注意的是這種嵌套查詢對(duì)于大型結(jié)果集和列名并友好,存在 N+1 的問(wèn)題,因?yàn)橄乱粭l SQL 會(huì)執(zhí)行 N 次去循環(huán)查詢,使用關(guān)聯(lián)查詢更合適。再者也可以開啟 mybatis 的懶查詢功能,嵌套的 SQL 不是一口氣順序執(zhí)行完,而是在使用的時(shí)候才會(huì)執(zhí)行下一條 SQL。例如執(zhí)行student.getScore().getSNO()才會(huì)執(zhí)行queryScore的 SQL。默認(rèn)情況下沒(méi)有開啟,需要在配置文件中設(shè)置
設(shè)置參數(shù) | 描述 | 默認(rèn)值 |
---|---|---|
lazyLoadingEnabled | 延遲加載的全局開關(guān),特定關(guān)聯(lián)關(guān)系中可通過(guò)設(shè)置 fetchType 屬性來(lái)覆蓋該項(xiàng)的開關(guān)狀態(tài) | false |
aggressiveLazyLoading | 當(dāng)開啟時(shí),任何方法的調(diào)用都會(huì)加載該對(duì)象的所有屬性。否則,每個(gè)屬性會(huì)按需加載 | false (true in ≤3.4.1) |
<!--mybatis-config.xml--> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/>
也可以在標(biāo)簽中設(shè)置 fetchType = “l(fā)azy” 開啟懶加載,會(huì)覆蓋全局的參數(shù)設(shè)置。
嵌套結(jié)果集
對(duì)于多表關(guān)聯(lián)查詢,一般在 SQL 中使用別名來(lái)避免字段名的重復(fù)。mybatis 要做的是將別名正確的映射到 JavaBean 屬性上。
<!--嵌套結(jié)果--> <resultMap id="associationDemoMap" type="student" autoMapping="true"> <association property="score" javaType="score"> <result property="SNO" column="SC_SNO"/> </association> </resultMap> <select id="queryStudentScore" resultMap="associationDemoMap"> SELECT SNAME, SSEX, CLASS, ST.SNO, SC.SNO AS SC_SNO FROM test.student st INNER JOIN test.score sc ON st.sno = sc.sno where CNO = '3-105'; </select>
通過(guò)設(shè)置標(biāo)簽指定了表列名和屬性之間的映射關(guān)系。但這樣如果字段很多,會(huì)需要一一指定,標(biāo)簽提供了columnPrefix屬性,指定別名的前綴,這樣可以重用resultMap
<resultMap id="associationDemoMap" type="student" autoMapping="true"> <!--columnPrefix 指定別名的前綴--> <association property="score" resultMap="anotherMap" columnPrefix="SC_" /> </resultMap> <!--方便重用--> <resultMap id="anotherMap" type="score" autoMapping="true"> </resultMap>
一對(duì)多關(guān)系
除了一對(duì)一的關(guān)系,還有一對(duì)多的關(guān)系,比如這里一個(gè)學(xué)生Student 對(duì)應(yīng)多門課的成績(jī)。 一對(duì)多對(duì)應(yīng)的情況下要在 resultMap 中使用 標(biāo)簽。首先需要調(diào)整 JavaBean 文件中兩個(gè)表之間的關(guān)系。
<!--Student.java--> private List<Score> score; public List<Score> getScore() { return score; } public void setScore(List<Score> score) { this.score = score; }
以嵌套結(jié)果集為例
<resultMap id="collectionDemoMap" type="student" autoMapping="true"> <!--多出了 ofType 屬性--> <collection property="score" ofType="score"> <result property="SNO" column="SC_SNO"/> </collection> </resultMap> <select id="queryStudentScore" resultMap="collectionDemoMap"> SELECT SNAME,SSEX,CLASS,ST.SNO,SC.SNO AS SC_SNO FROM test.student st INNER JOIN test.score sc ON st.sno = sc.sno </select>
注意到相比 association 多了一個(gè)屬性ofType,是用來(lái)表示 List 集合中的類型的。其他屬性的用法同 association 是一樣的。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- MyBatis實(shí)現(xiàn)模糊查詢的幾種方式
- Mybatis多表關(guān)聯(lián)查詢的實(shí)現(xiàn)(DEMO)
- mybatis 模糊查詢的實(shí)現(xiàn)方法
- Mybatis 一對(duì)多和多對(duì)一關(guān)聯(lián)查詢問(wèn)題
- mybatis 實(shí)現(xiàn) SQL 查詢攔截修改詳解
- MyBatis之自查詢使用遞歸實(shí)現(xiàn) N級(jí)聯(lián)動(dòng)效果(兩種實(shí)現(xiàn)方式)
- Mybatis查詢記錄條數(shù)的實(shí)例代碼
- MyBatis實(shí)現(xiàn)動(dòng)態(tài)查詢、模糊查詢功能
- mybatis分頁(yè)及模糊查詢功能實(shí)現(xiàn)
- MyBatis查詢時(shí)屬性名和字段名不一致問(wèn)題的解決方法
相關(guān)文章
SpringBoot將logback替換成log4j2的操作步驟
文章介紹了如何在SpringBoot項(xiàng)目中將默認(rèn)的日志框架logback替換為log4j2,以利用log4j2的高性能異步日志記錄特性,特別是通過(guò)Disruptor實(shí)現(xiàn)的無(wú)鎖化隊(duì)列,提高了日志處理速度,同時(shí),文章提供了詳細(xì)的配置步驟,需要的朋友可以參考下2024-10-10Java接口自動(dòng)化測(cè)試框架設(shè)計(jì)之Get請(qǐng)求方法和測(cè)試詳解
這篇文章主要介紹了Java接口自動(dòng)化測(cè)試框架設(shè)計(jì) Get請(qǐng)求方法和測(cè)試,框架設(shè)計(jì)我們只是介紹基本的組件,而且框架設(shè)計(jì)沒(méi)有想象那么難,一步一步跟著做就會(huì)了。這篇我們來(lái)演示,如果通過(guò)Java代碼來(lái)實(shí)現(xiàn)一個(gè)用純代碼實(shí)現(xiàn)Http中的Get請(qǐng)求過(guò)程,需要的朋友可以參考下2019-07-07Java HttpServletResponse響應(yīng)實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了Java HttpServletResponse響應(yīng)實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05使用Maven 搭建 Spring MVC 本地部署Tomcat的詳細(xì)教程
這篇文章主要介紹了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08