Mybatis學習記錄(三)--Mybatis配置檔案詳解
關於mybatis的配置檔案,主要有兩個,一個是SqlMapperConfig.xml檔案一個是mapper.xml檔案,分別對這兩個進行深入全面學習.
一.SqlMapperConfig.xml檔案
1.標籤概況
在SqlMapperConfig.xml中主要有以下標籤,其中環境集合environments和spring整合後廢除不用.objectFactory和plugins不經常使用.
- properties(屬性)
- settings(全域性配置引數)
- typeAliases(類型別名)
- typeHandlers(型別處理器)
- objectFactory(物件工廠)
- plugins(外掛)
- environments(環境集合屬性物件)
- environment(環境子屬性物件)
- transactionManager(事務管理)
- dataSource(資料來源)
- mappers(對映器)
2.properties
此標籤主要用來引用額外的properties檔案,用來解耦xml和其他特殊的配置引數,比如對於資料庫的配置,可以單獨建立一個db.properties檔案來儲存
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shopdemo
jdbc.username=root
jdbc.password =123456
然後在配置檔案中使用$符號來引用
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--這裡引入我們的配置檔案-->
<properties resource="db.properties">
<!--這裡面也可以單獨定義引數-->
<property name="" value=""/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!--這裡使用${}來呼叫配置檔案裡面的引數-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
</configuration>
如果使用這種方式就要了解mybatis對外部引數引用的過程,不然如果命名一樣的引數會出現覆蓋現象
1. 在 properties 元素體內定義的屬性首先被讀取。
2. 然後會讀取properties 元素中resource或 url 載入的屬性,它會覆蓋已讀取的同名屬性。
3. 最後讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性。
因此,通過parameterType傳遞的屬性具有最高優先順序,resource或 url 載入的屬性次之,最低優先順序的是 properties 元素體內定義的屬性。
3.settings
這個是mybatis執行引數的配置,執行引數將會影響mybatis的執行行為。具體可配置的如下表.
4.typeAliases
這個是配置類型別名,一般針對自己寫的pojo類,因為寫全部的類路徑名實在是太長了,用這個定義下會省事很多.
1.預設別名
別名 | 對映的型別 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
2.自定義別名
<typeAliases>
<!--單個對映配置-->
<typeAlias type="com.aust.model.User"/>
<!--對映包內的所有檔案,預設別名為java檔案類名,首字母大小寫均可,但一般小寫-->
<package name="com.aust.model"/>
</typeAliases>
5.typeHandlers
型別處理器用於java型別和jdbc型別對映,這個一般mybatis自帶的型別處理器基本上滿足日常需求,不需要單獨定義。具體轉換可以查詢相關文件
6.objectFactory
MyBatis 每次建立結果物件的新例項時,它都會使用一個物件工廠(ObjectFactory)例項來完成。預設的物件工廠需要做的僅僅是例項化目標類,要麼通過預設構造方法,要麼在引數對映存在的時候通過引數構造方法來例項化。預設情況下,我們不需要配置,mybatis會呼叫預設實現的objectFactory。
7.plugin
plugins 是一個可選配置。mybatis中的plugin其實就是個interceptor, 它可以攔截Executor 、ParameterHandler 、ResultSetHandler 、StatementHandler 的部分方法,處理我們自己的邏輯。Executor就是真正執行sql語句的東西, ParameterHandler 是處理我們傳入引數的,還記得前面講TypeHandler的時候提到過,mybatis預設幫我們實現了不少的typeHandler, 當我們不顯示配置typeHandler的時候,mybatis會根據引數型別自動選擇合適的typeHandler執行,其實就是ParameterHandler 在選擇。ResultSetHandler 就是處理返回結果的。
8.mappers
//使用相對於類路徑的資源
<mapper resource="sqlmap/User.xml" />
//使用完全限定路徑
<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
//使用mapper介面類路徑,也就是說使用mapper代理開發dao
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
//注意:此種方法要求mapper介面名稱和mapper對映檔名稱相同,且放在同一個目錄中。
//註冊指定包下的所有mapper介面,也就是說使用mapper代理開發dao
<package name="cn.itcast.mybatis.mapper"/>
//注意:此種方法要求mapper介面名稱和mapper對映檔名稱相同,且放在同一個目錄中。
二.Mapper.xml檔案
1.輸入型別parameterType
輸入型別可以為簡單型別,pojo類,hashmap等.
1.傳遞簡單型別
mybatis會根據預設別名typeAliases來自動解析型別
//傳入簡單型別int
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
</select>
2.傳入hashmap
傳入hashmap的話,則#和$取出的引數都是hashmap中的key
<!--測試使用hashmap傳入引數-->
<select id="findUser" parameterType="java.util.HashMap" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id} AND nickname LIKE '%${nickname}%'
</select>
測試程式碼
//測試取出單個
@Test
public void findUserTest(){
//獲取sqlsession
SqlSession session = factory.openSession();
//建立mapper代理
UserMapper mapper = session.getMapper(UserMapper.class);
//利用mapper代理查詢
HashMap<String,Object> map = new HashMap<>();
map.put("id",1);
map.put("nickname","牛");
User u = mapper.findUser(map);
session.close();
System.out.println(u);
}
有問題的就是當hashmap中對應的引數不存在的話,程式並不會報錯,而是查不到結果,這裡可能引發一些異常
3.傳遞pojo物件
這個如果沒使用typeAliases來對映的話就直接傳遞完整類路徑,使用的話就可以傳遞簡單名稱
<!--根據id查詢出使用者資訊(查詢一條資料)-->
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
</select>
2.輸出型別resultType
和輸入型別用法差不多
1.輸出簡單型別
<!--輸出簡單型別int-->
<select id="findUserCount" parameterType="java.lang.String" resultType="int">
SELECT COUNT(*) from user WHERE nickname LIKE '%${value}%'
</select>
要注意的是輸出簡單型別必須查詢出來的結果集有一條記錄,最終將第一個欄位的值轉換為輸出型別。
使用session的selectOne可查詢單條記錄。
2.輸出pojo型別
mybatis使用session呼叫selectOne查詢單條記錄。和輸入方式一樣的用法
3.pojo列表
mybatis使用session的selectList方法獲取pojo列表。返回資料為List
4.輸出hashmap
輸出pojo物件可以改用hashmap輸出型別,將輸出的欄位名稱作為map的key,value為欄位值。
3.輸出型別resultMap
resultType可以指定pojo將查詢結果對映為pojo,但需要pojo的屬性名和sql查詢的列名一致方可對映成功。如果sql查詢欄位名和pojo的屬性名不一致,可以通過resultMap將欄位名和屬性名作一個對應關係,resultMap實質上還需要將查詢結果對映到pojo物件中。resultMap可以實現將查詢結果對映為複雜型別的pojo,比如在查詢結果對映物件中包括pojo和list實現一對一查詢和一對多查詢。
1.定義resultMap
<!--id:此resultMap的唯一表示
type:對映的型別
-->
<resultMap id="userMap" type="com.aust.model.User">
<!--id:該查詢記錄的唯一標示,也就是主鍵
result:普通列對映標示
column:要對映的查詢結果sql列
property;要對映為pojo的那個屬性名
-->
<id column="id_" property="id"/>
<result column="username_" property="username"/>
</resultMap>
2.使用resultMap
<!--根據id查詢出使用者資訊(查詢一條資料)-->
<select id="findUserById" parameterType="int" resultMap="userMap">
SELECT id id_,username username_,password,nickname,status FROM user WHERE id=#{id}
</select>
從程式碼可以看出,我給id和username分別起了別名id_,username_,然後返回型別為之前定義的userMap,這樣的話查詢結果自動會把id_對映為User類的id,username_對映為User類的username.
下一篇關聯查詢會介紹更多
3.動態sql
通過mybatis提供的各種標籤方法實現動態拼接sql。
1.if標籤
<!-- 傳遞pojo綜合查詢使用者資訊 -->
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</select>
2.where標籤
where主要解決了上面單純用if標籤還要寫where 1=1這樣的多餘條件的情況.
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</where>
</select>
3.foreach標籤
foreach遍歷集合和陣列進行sql語句拼接,看下面例子
SELECT * FROM USERS WHERE username LIKE '%張%' AND id IN (10,89,16)
有上面這樣的sql,那麼用foreach假設傳了陣列a{10,89,16}或者集合a{10,89,16}
<foreach collection="a" open=" and id in(" close=")" item="id" separator="," >
#{id}
</foreach>
- collection:傳入的陣列或者集合名稱
- open:遍歷開始前加入的字首,這裡是AND id IN (
- close:遍歷結束加入的字尾,這裡是)
- item:要遍歷的專案,為pojo的時候,取出引數就要用#{pojo.屬性名}
- separator:每個專案之間的分隔符
如果傳遞的為陣列的話,裡面還有有個index屬性,來表示陣列的下標
4.sql片段
Sql中可將重複的sql提取出來,使用時用include引用即可,最終達到sql重用的目的
sql片段用sql標籤包裹起來
<sql id="query_user_where">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</sql>
引用方式
如果引用的為其他mapper.xml的片段,則需要使用 namespace.sql片段名
專案示例: