MyBatis實(shí)現(xiàn)SQL映射文件
1 SQL 映射文件介紹
映射器是 MyBatis 中最復(fù)雜并且是最重要的組件。它由一個(gè)接口和 SQL 映射文件(或者注解)組成。在映射器中我們可以配置各類 SQL、動(dòng)態(tài) SQL、緩存、存儲(chǔ)過(guò)程、級(jí)聯(lián)等復(fù)雜的內(nèi)容。
以下是 SQL 映射文件的部分元素介紹
元素 | 描述 |
---|---|
cache | 該命名空間的緩存配置 |
cache-ref | 引用其它命名空間的緩存配置 |
resultMap | 描述如何從數(shù)據(jù)庫(kù)結(jié)果集中加載對(duì)象,它是最復(fù)雜也是最強(qiáng)大的元素 |
sql | 可被其它語(yǔ)句引用的可重用語(yǔ)句塊 |
select | 映射查詢語(yǔ)句 |
insert | 映射插入語(yǔ)句 |
update | 映射更新語(yǔ)句 |
delete | 映射刪除語(yǔ)句 |
2 select 元素
select 元素表示 SQL 的 select 語(yǔ)句,用于查詢,以下是 select 元素的部分屬性
屬性 | 描述 |
---|---|
id | 在命名空間中唯一的標(biāo)識(shí)符,可以被用來(lái)引用這條語(yǔ)句 |
parameterType | 將會(huì)傳入這條語(yǔ)句的參數(shù)類的全類名或別名。這個(gè)屬性是可選的,因?yàn)?MyBatis 可以通過(guò)類型處理器(TypeHandler) 推斷出具體傳入語(yǔ)句的參數(shù),默認(rèn)值為未設(shè)置(unset) |
resultType | 從這條語(yǔ)句中返回的期望類型的類的全類名或別名。 注意如果返回的是集合,那應(yīng)該設(shè)置為集合包含的類型,而不是集合本身??梢允褂?resultType 或 resultMap,但不能同時(shí)使用 |
resultMap | 外部 resultMap 的命名引用。結(jié)果集的映射是 MyBatis 最強(qiáng)大的特性,如果你對(duì)其理解透徹,許多復(fù)雜映射的情形都能迎刃而解??梢允褂?resultMap 或 resultType,但不能同時(shí)使用 |
flushCache | 將其設(shè)置為 true 后,只要語(yǔ)句被調(diào)用,都會(huì)導(dǎo)致本地緩存和二級(jí)緩存被清空,默認(rèn)值:false |
useCache | 將其設(shè)置為 true 后,將會(huì)導(dǎo)致本條語(yǔ)句的結(jié)果被二級(jí)緩存緩存起來(lái),默認(rèn)值:對(duì) select 元素為 true |
timeout | 這個(gè)設(shè)置是在拋出異常之前,驅(qū)動(dòng)程序等待數(shù)據(jù)庫(kù)返回請(qǐng)求結(jié)果的秒數(shù)。默認(rèn)值為未設(shè)置(unset)(依賴驅(qū)動(dòng)) |
fetchSize | 這是一個(gè)給驅(qū)動(dòng)的提示,嘗試讓驅(qū)動(dòng)程序每次批量返回的結(jié)果行數(shù)和這個(gè)設(shè)置值相等。 默認(rèn)值為未設(shè)置(unset)(依賴驅(qū)動(dòng)) |
statementType | STATEMENT,PREPARED 或 CALLABLE 中的一個(gè)。這會(huì)讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認(rèn)值:PREPARED |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等價(jià)于 unset) 中的一個(gè),默認(rèn)值為 unset (依賴驅(qū)動(dòng)) |
databaseId | 如果配置了數(shù)據(jù)庫(kù)廠商標(biāo)識(shí) (databaseIdProvider) 并且存在兩個(gè)相同的語(yǔ)句,一個(gè)帶 databaseId 而另一個(gè)不帶,MyBatis 會(huì)優(yōu)先加載帶有 databaseId 的語(yǔ)句。如果 databaseId 與當(dāng)前數(shù)據(jù)庫(kù)匹配,則不帶 databaseId 的相同語(yǔ)句將被忽略。未設(shè)置 databaseId 使用通用 SQL 規(guī)則 |
resultOrdered | resultOrdered:這個(gè)設(shè)置僅對(duì)嵌套結(jié)果 select 語(yǔ)句適用:如果為 true,就是假設(shè)包含了嵌套結(jié)果集或是分組,這樣的話當(dāng)返回一個(gè)主結(jié)果行的時(shí)候,就不會(huì)發(fā)生有對(duì)前面結(jié)果集的引用的情況。 這就使得在獲取嵌套的結(jié)果集的時(shí)候不至于導(dǎo)致內(nèi)存不夠用。默認(rèn)值:false |
resultSets | 這個(gè)設(shè)置僅對(duì)多結(jié)果集的情況適用。它將列出語(yǔ)句執(zhí)行后返回的結(jié)果集并給每個(gè)結(jié)果集一個(gè)名稱,名稱是逗號(hào)分隔的 |
3 insert 元素
屬性 | 描述 |
---|---|
id | 在命名空間中唯一的標(biāo)識(shí)符,可以被用來(lái)引用這條語(yǔ)句 |
parameterType | 將會(huì)傳入這條語(yǔ)句的參數(shù)的類全限定名或別名。這個(gè)屬性是可選的,因?yàn)?MyBatis 可以通過(guò)類型處理器(TypeHandler)推斷出具體傳入語(yǔ)句的參數(shù),默認(rèn)值為未設(shè)置(unset) |
flushCache | 將其設(shè)置為 true 后,只要語(yǔ)句被調(diào)用,都會(huì)導(dǎo)致本地緩存和二級(jí)緩存被清空,默認(rèn)值:(對(duì) insert、update 和 delete 語(yǔ)句)true |
timeout | 這個(gè)設(shè)置是在拋出異常之前,驅(qū)動(dòng)程序等待數(shù)據(jù)庫(kù)返回請(qǐng)求結(jié)果的秒數(shù)。默認(rèn)值為未設(shè)置(unset)(依賴數(shù)據(jù)庫(kù)驅(qū)動(dòng)) |
statementType | 可選 STATEMENT,PREPARED 或 CALLABLE。這會(huì)讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認(rèn)值:PREPARED |
useGeneratedKeys | (僅適用于 insert 和 update)這會(huì)令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來(lái)取出由數(shù)據(jù)庫(kù)內(nèi)部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)的自動(dòng)遞增字段),默認(rèn)值:false |
keyProperty | (僅適用于 insert 和 update)指定能夠唯一識(shí)別對(duì)象的屬性,MyBatis 會(huì)使用 getGeneratedKeys 的返回值或 insert 語(yǔ)句的 selectKey 子元素設(shè)置它的值,默認(rèn)值:未設(shè)置(unset)。如果生成列不止一個(gè),可以用逗號(hào)分隔多個(gè)屬性名稱。不能和keyColumn連用 |
keyColumn | (僅適用于 insert 和 update)設(shè)置生成鍵值在表中的列名,在某些數(shù)據(jù)庫(kù)(像 PostgreSQL)中,當(dāng)主鍵列不是表中的第一列的時(shí)候,是必須設(shè)置的。如果生成列不止一個(gè),可以用逗號(hào)分隔多個(gè)屬性名稱。不能和keyProperty連用 |
databaseId | 同 select 元素 |
主鍵回填
在 MyBatis 中,若表中的主鍵設(shè)置為自增,插入數(shù)據(jù)時(shí)沒(méi)有插入主鍵,但是又想獲得數(shù)據(jù)庫(kù)中該條數(shù)據(jù)的主鍵,那么可以通過(guò)設(shè)置 useGeneratedKeys=”true”,然后再把 keyProperty 設(shè)置到目標(biāo)屬性(如 User 類中的 id 屬性)上來(lái)獲得該值。
<insert id="insertUser" parameterType="com.entity.User" useGeneratedKeys="true" keyProperty="id"> insert into person(name, age, sex) values (#{name}, #{age}, #{sex}); </insert>
//添加一個(gè)用戶數(shù)據(jù) @Test public void testInsertUser() { String statement = "com.mapper.UserMapper.insertUser"; User user = new User(); user.setName("孫尚香"); user.setAge(24); user.setSex("女"); int i = sqlSession.insert(statement, user); System.out.println( (i>0)? "添加成功!":"添加失??!"); //提交插入的數(shù)據(jù) sqlSession.commit(); sqlSession.close(); // 輸出返回的主鍵值 System.out.println("返回的主鍵值=" + user.getId()); }
自定義主鍵并且可以在 Java 中通過(guò)屬性獲得該值
在 MyBatis 中可以通過(guò) selectKey 元素自定義主鍵,以下是其屬性介紹
- keyProperty:selectKey 需要設(shè)置的目標(biāo)屬性
- resultType:結(jié)果類型
- order:可以設(shè)置為 BEFORE 或 AFTER ,表示先設(shè)置主鍵,后執(zhí)行插入語(yǔ)句或先執(zhí)行插入語(yǔ)句,后設(shè)置主鍵
<insert id="insertUser" parameterType="com.entity.User" > <selectKey keyProperty="id" resultType="int" order="BEFORE"> select ROUND(RAND()*1000) </selectKey> insert into person(id, name, age, sex) values (#{id}, #{name}, #{age}, #{sex}); </insert>
@Test public void testInsertUser() { String statement = "com.mapper.UserMapper.insertUser"; User user = new User(); user.setName("鄭旦"); user.setAge(24); user.setSex("女"); int i = sqlSession.insert(statement, user); System.out.println( (i>0)? "添加成功!":"添加失??!"); //提交插入的數(shù)據(jù) sqlSession.commit(); sqlSession.close(); // 輸出返回的主鍵值 System.out.println("返回的主鍵值=" + user.getId()); }
4 update 和 delete 元素
update 和 delete 元素在使用上比較簡(jiǎn)單,所以這里把它們放在一起論述。它們和 insert 元素的屬性差不多,執(zhí)行完后也會(huì)返回一個(gè)整數(shù),用來(lái)表示該 SQL 語(yǔ)句影響了多少條數(shù)據(jù)庫(kù)記錄。
<!-- 根據(jù) id 更新用戶 --> <update id="updateUser"> update person set name = #{name}, age = #{age},sex = #{sex} where id = #{id} </update> <!-- 根據(jù) id 刪除用戶 --> <delete id="deleteUser" parameterType="int"> delete from person where id = #{id} </delete>
5 sql 元素
sql 元素是用來(lái)定義可重用的 sql 代碼片段,這樣在字段比較多的時(shí)候,以便在其它語(yǔ)句中使用。需要結(jié)合 include 元素一起使用,以下是代碼示例。
<!--定義sql代碼片段--> <sql id="userCols"> id,username,age,sex </sql> <!-- 查詢所有用戶 --> <select id="selectAllUser" resultType="com.entity.User"> select <include refid="userCols"/> from person </select>
6 parameterType 元素
parameterType 元素可以輸入以下類型:
- Java 基本數(shù)據(jù)類型
- POJO 類型
- Map 類型
<!-- 通過(guò) 普通數(shù)據(jù)類型 int 查詢一個(gè)用戶 --> <select id="selectUserById" parameterType="int" resultType="com.entity.User"> select * from person where id = #{id}; </select> <!-- 通過(guò) POJO 類型 User 添加用戶--> <insert id="insertUser" parameterType="com.entity.User"> insert into person(id,username,age,sex) values (#{id},#{username},#{age},#{sex}); </insert> <!-- 通過(guò) 嵌套 POJO 類型 查詢一個(gè)用戶,QueryVo 類中定義了 User user 屬性 --> <select id="selectUserByUserNameAndAge" parameterType="com.entity.QueryVo" resultType="com.entity.User"> select * from person where name = #{user.name} and age = #{user.age}; </select> <!-- 通過(guò) Map 類型 查詢一個(gè)用戶, HashMap<String, Object> map = new HashMap<>(); map.put("name","趙飛燕"); map.put("age",24); 通過(guò) key 獲得 map 中的 value--> <select id="selectUserByMap" parameterType="hashmap" resultType="com.entity.User"> select * from person where name = #{name} and age = #{age}; </select>
7 resultType 元素
resultType 元素和 parameterType 元素用法差不多,一個(gè)是輸出,一個(gè)是輸入。resultType 元素可以輸出以下類型:
- Java 基本數(shù)據(jù)類型
- POJO 對(duì)象
- POJO 對(duì)象列表
- Map 對(duì)象列表
<!-- 統(tǒng)計(jì)用戶總數(shù)量,輸出為一個(gè)整數(shù) int --> <select id="countUsers" resultType="int"> select count(1) from person </select> <!-- 通過(guò) id 查詢一個(gè)用戶,輸出為一個(gè) User --> <select id="selectUserById" parameterType="int" resultType="com.entity.User"> select * from personwhere id = #{id}; </select> <!-- 查詢所有用戶,輸出為一個(gè) List<User> 列表 --> <select id="selectAllUser" resultType="com.entity.User"> select * from person </select> <!-- 查詢所有用戶, 輸出為一個(gè) List<HashMap<String, Object>> Map 列表--> <select id="selectAllUser" resultType="hashmap"> select * from person </select>
8 resultMap 元素(重要)
我們?cè)谑褂?resultType 的時(shí)候,需要保證數(shù)據(jù)庫(kù)表中的字段名和表對(duì)應(yīng)實(shí)體類的屬性名稱一致才行(包括駝峰命名規(guī)則)。那不一致怎么辦,查詢的時(shí)候可以給列名起個(gè)別名,但是一般不建議這樣做,而是通過(guò) resultMap 元素進(jìn)行一個(gè)轉(zhuǎn)換。
<!-- id:唯一標(biāo)識(shí),type:需要映射的 Java 類型--> <resultMap id="userMap" type="com.entity.User"> <!-- 與主鍵字段的對(duì)應(yīng),property對(duì)應(yīng)實(shí)體屬性,column對(duì)應(yīng)表字段 --> <id property="userId" column="id"/> <!-- 與非主鍵字段的對(duì)應(yīng),property對(duì)應(yīng)實(shí)體屬性,column對(duì)應(yīng)表字段 --> <result property="userName" column="username"/> <result property="userAge" column="age"/> <result property="userSex" column="sex"/> </resultMap> <!-- 查詢所有用戶,返回集為resultMap類型,resultMap的value上面配置的 id=userMap 要一致--> <select id="selectAllUser" resultMap="userMap"> select * from person </select>
上述代碼是不是很眼熟,在 MyBatis 案例中使用了 @ResultMap 注解來(lái)實(shí)現(xiàn)上述代碼
resultMap 元素的組成
<!-- autoMapping:指定是否自動(dòng)映射查詢結(jié)果的列到 Java 對(duì)象的屬性。 默認(rèn)為開(kāi)啟(true),如果設(shè)置為 false,則需要手動(dòng)配置每個(gè)屬性的映射關(guān)系 --> <resultMap id="標(biāo)識(shí)" type="輸出類型" extends="繼承其他 <resultMap>" autoMapping="自動(dòng)映射"> <constructor><!--構(gòu)造器注入屬性值--> <!-- 構(gòu)造器標(biāo)識(shí),一般為主鍵 --> <!-- column對(duì)應(yīng)表字段,name對(duì)應(yīng)實(shí)體屬性 --> <idArg column="id" name="userId" javaType="int"/> <!-- 構(gòu)造器參數(shù) --> <arg column="username" name="userName" javaType="string"/> </constructor> <!-- id 與主鍵字段的對(duì)應(yīng),property對(duì)應(yīng)實(shí)體屬性,column對(duì)應(yīng)表字段 --> <id property="userId" column="id"/> <!-- result 與非主鍵字段的對(duì)應(yīng),property對(duì)應(yīng)實(shí)體屬性,column對(duì)應(yīng)表字段 --> <result property="userName" column="username"/> <association/><!--高級(jí)映射,一對(duì)一映射--> <collection /><!--高級(jí)映射,一對(duì)多映射--> <discriminator> <case/> </discriminator><!--根據(jù)返回的字段的值封裝不同的類型--> </resultMap>
9 參考文檔
到此這篇關(guān)于MyBatis實(shí)現(xiàn)SQL映射文件的文章就介紹到這了,更多相關(guān)MyBatis SQL映射文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC之mvc:resources如何處理靜態(tài)資源
這篇文章主要介紹了Spring MVC之mvc:resources如何處理靜態(tài)資源問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03SpringBoot 過(guò)濾器與攔截器實(shí)例演示
本文通過(guò)示例代碼給大家講解SpringBoot 過(guò)濾器與攔截器的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11SpringBoot整合Mybatis實(shí)現(xiàn)多數(shù)據(jù)源配置與跨數(shù)據(jù)源事務(wù)實(shí)例
開(kāi)發(fā)中經(jīng)常有這樣的需要: 讀寫分離。微服務(wù)環(huán)境下可以實(shí)現(xiàn)一個(gè)服務(wù)讀取一個(gè)數(shù)據(jù)庫(kù),另一個(gè)服務(wù)寫庫(kù)。但是在實(shí)際應(yīng)用中有時(shí)也需要在一個(gè)服務(wù)中讀寫不同的數(shù)據(jù)庫(kù)??梢栽谝粋€(gè)SpringBoot單體項(xiàng)目中配置多個(gè)數(shù)據(jù)源解決讀寫庫(kù)分離2022-11-11springboot新建項(xiàng)目jdk只有17/21,無(wú)法選中1.8解決辦法
最近博主也有創(chuàng)建springboot項(xiàng)目,發(fā)現(xiàn)了IntelliJ IDEA在通過(guò)Spring Initilizer初始化項(xiàng)目的時(shí)候已經(jīng)沒(méi)有java8版本的選項(xiàng)了,這里給大家總結(jié)下,這篇文章主要給大家介紹了springboot新建項(xiàng)目jdk只有17/21,無(wú)法選中1.8的解決辦法,需要的朋友可以參考下2023-12-12java操作oracle數(shù)據(jù)庫(kù)示例
這篇文章主要介紹了java操作oracle數(shù)據(jù)庫(kù)示例,需要的朋友可以參考下2014-04-04深入理解Java并發(fā)編程之LinkedBlockingQueue隊(duì)列
本文主要介紹了Java并發(fā)編程之LinkedBlockingQueue隊(duì)列,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04springboot如何使用vue打包過(guò)的頁(yè)面資源
這篇文章主要介紹了springboot如何使用vue打包過(guò)的頁(yè)面資源,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12解決springboot 連接 mysql 時(shí)報(bào)錯(cuò) using password: NO的方案
在本篇文章里小編給大家整理了關(guān)于解決springboot 連接 mysql 時(shí)報(bào)錯(cuò) using password: NO的方案,有需要的朋友們可以學(xué)習(xí)下。2020-01-01Java生成的隨機(jī)數(shù)靠譜嗎?多少次會(huì)重復(fù)?
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java生成的隨機(jī)數(shù)靠不靠譜展開(kāi),文中有非常詳細(xì)的介紹,需要的朋友可以參考下2021-06-06