1 <!DOCTYPE configuration 2 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 4 <configuration> 5 <!-- 配置 mybatis 的環境 --> 6 <environments default="mysql"> 7 <!-- 配置 mysql 的環境 --> 8 <environment id="mysql"> 9 <!-- 配置事務的類型 --> 10 <transactionManager type="JDBC"></transactionManager> 11 <!-- 配置鏈接數據庫的信息:用的是數據源(鏈接池) --> 12 <dataSource type="POOLED"> 13 <property name="driver" value="com.mysql.jdbc.Driver"/> 14 <property name="url" value="jdbc:mysql://localhost:3306/ee50"/> 15 <property name="username" value="root"/> 16 <property name="password" value="1234"/> 17 </dataSource> 18 </environment> 19 </environments> 20 <!-- 告知 mybatis 映射配置的位置 --> 21 <mappers> 22 <mapper resource="com/itheima/dao/IUserDao.xml"/> 23 </mappers> 24 </configuration>
配置順序html
-properties(屬性)
--property
-settings(全局配置參數)
--setting
-typeAliases(類型別名)
--typeAliase
--package
-typeHandlers(類型處理器)
-objectFactory(對象工廠)
-plugins(插件)
-environments(環境集合屬性對象)
--environment(環境子屬性對象)
---transactionManager(事務管理)
---dataSource(數據源)
-mappers(映射器)
--mapper
--package
1 //1.讀取配置文件 2 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); 3 //2.建立 SqlSessionFactory 的構建者對象 4 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 5 //3.使用構建者建立工廠對象 6 SqlSessionFactorySqlSessionFactory factory = builder.build(in); 7 //4.使用 SqlSessionFactory 生產 SqlSession 對象 8 SqlSession session = factory.openSession(); 9 //5.使用 SqlSession 建立 dao 接口的代理對象 10 IUserDao userDao = session.getMapper(IUserDao.class); 11 //6.使用代理對象執行查詢全部方法 12 List<User> users = userDao.findAll();
在使用基於註解的 Mybatis 配置時,請移除 xml 的映射配置(IUserDao.xml).java
#{}表示一個佔位符號
經過#{}能夠實現 preparedStatement 向佔位符中設置值,自動進行 java 類型和 jdbc 類型轉換,
#{}能夠有效防止 sql 注入。 #{}能夠接收簡單類型值或 pojo 屬性值。 若是 parameterType 傳輸單個簡單類
型值,#{}括號中能夠是 value 或其它名稱。
${}表示拼接 sql 串
經過${}能夠將 parameterType 傳入的內容拼接在 sql 中且不進行 jdbc 類型轉換, ${}能夠接收簡
單類型值或 pojo 屬性值,若是 parameterType 傳輸單個簡單類型值,${}括號中只能是 value。
resultMap 標籤能夠創建查詢的列名和實體類的屬性名稱不一致時創建對應關係。從而實現封裝。
在 select 標籤中使用 resultMap 屬性指定引用便可。同時 resultMap 能夠實現將查詢結果映射爲複雜類
型的 pojo,好比在查詢結果映射對象中包括 pojo 和 list 實現一對一查詢和一對多查詢。
<!-- 創建 User 實體和數據庫表的對應關係
type 屬性:指定實體類的全限定類名
id 屬性:給定一個惟一標識,是給查詢 select 標籤引用用的。
-->
<resultMap type="com.itheima.domain.User" id="userMap"> • <id column="id" property="userId"/> • <result column="username" property="userName"/> • <result column="sex" property="userSex"/> • <result column="address" property="userAddress"/> • <result column="birthday" property="userBirthday"/> </resultMap>
id 標籤:用於指定主鍵字段
result 標籤:用於指定非主鍵字段
column 屬性:用於指定數據庫列名
property 屬性:用於指定實體類屬性
<!-- 配置查詢全部操做 -->mysql
<select id="findAll" resultMap="userMap"> select * from user </select>
7.1 SqlSessionFactoryBuilder git
SqlSessionFactoryBuilder 做用在於建立 SqlSessionFactory ,建立成功後,SqlSessionFactoryBuilder 就失去了做用,因此它只能存在於建立 Sq!SessionFactory 的方法中,而不要讓其長期存在。github
7.2 SqlSessionFactory spring
SqlSessionFactory 能夠被認爲是 個數據庫鏈接池,它的做用是建立 SqlSession 接口對象。由於 MyBatis 本質就是 Java 數據庫的操做,因此 SqlSessionFactory 的生命週期存在於整個 MyBatis 應用之中,因此 旦建立了 SqlSessionFactory 就要長期保存它,直至再也不使用 MyBatis 應用,因此能夠認爲 SqlSessionFactory 的生命週期就等同於 MyBati應用週期。 因爲 sqlSessionFactory 個對數據庫的鏈接池,因此它佔據着數據庫的鏈接資源。若是建立多個 SqlSessionFactory ,那麼就存在多個數據庫鏈接池,這樣不利於對數據庫資源的控制,也會致使數據庫鏈接資源被消耗光,出現系統密機等狀況,因此儘可能避免發生這樣的狀況。所以在 般的應用中我 每每希SqlSessionFactory 做爲 個單例,讓它在應用中被共享。sql
7.3 SqlSession 數據庫
若是說 SqlSes sionFactory 至關於數據庫鏈接池,那麼 SqlSession 就相 當於一個數據庫鏈接( Connection 象) ,你能夠在一個事務裏面執行多條 QL ,而後經過它的 commitrollback 等方法 提交或者回滾事務。因此它應該存活在 個業務請求中,處理完整個請求後,應該關閉這條鏈接,讓它歸還給 SqlSessionFactory 不然數據庫資源就很快被耗費精光,系統就會癱瘓,因此用 可... catch .. . finally ...語句來保證其正確關閉。編程
7.4 Mapper緩存
Mapper 是一個接口,它由 Sq!Session 所建立,因此它的最大生命週期至多和 Sq!Session保持 一致,儘管它很好用,可是因爲 SqlSession 關閉,它的數據庫鏈接資源也會消失,因此它的生命週期應該小於等於 Sq!Se ssion 的生命週期 Mapper 表的是 個請求中的業務處理,因此它應該在一個請求中,一旦處理完了相關的業務,就應該廢棄它。
一種用 SqlSession直接發送,另外 種經過 SqlSessio 獲取 Mapper 接口再發送。筆者建議採用 SqlSession 獲取Mapper 的方式,理由以下使用 Mapper 接口編程能夠消除 SqlSession 帶來的功能性代碼,提升可讀性,而 SqlSession 發送 SQL 須要一個 SQL id 去匹配 SQL ,比較晦澀難懂。使用 Mapper接口 roleMapper.getRole(lL)則 是徹底面向對象的語言 更能體現業務的邏輯。使用 Mapper.getRole( 1 )方式, IDE 會提示錯誤和校驗,而使用sqlSess on. electOne(「getRole」, lL )語法,只有在運行中才能知道是否會產生錯誤。
settings是MyBatis 最複雜的配置,它能深入影響 MyBatis 底層的運行,可是在大部份狀況下MyBatis 配置 使用默認值即可以運行,因此在大部分狀況下不須要大量配置它,只須要修改一些經常使用的規 便可 好比自動映射、駝峯命名映射、級聯規則、 是否啓動緩存、執行器(Executor )類型等 setting 配置項說明 如表.....
10.1 事務管理器(transactionManager)
MyBatis Transaction 提供了兩個實現類: JdbcTransaction和ManagedTransaction,因而它對應 兩種工廠 JdbcTransactionFactory和ManagedTransactionFactory 這個工廠須要實 TransactionFactory 接口 ,經過它們會生成對應 Transaction 象。因而能夠把事務管理器配置成爲如下兩種方式:
<transactionManager type= 」 JDBC 」 /> <transactionManager type= 」 MANAGED '’/>
• JDBC 使用 JdbcTransactionFactory 生成的 JdbcTransaction 象實現。它是以 JDBC的方式對數據庫的提交和回滾進行操做。 • MANAGED 使用 managedTransactionFactory 生成的 ManagedTransaction 象實現。它的提交和回滾方法不用任何操做,而是把事務交給容器處理。在默認狀況下,它會關閉鏈接,然而 些容器並不但願這樣,因 須要將 closeConnection 屬性設置爲false 來阻止它默認的關閉行爲。
也能夠自定義transactionManager。
10.2 數據源(datasource)
<dataSource type=」UN POOLED」> <dataSource type= 」 POOLED」> <dataSource type= 」 JNDI 」 >
POOLED 數據源 POOLED 用「池」的概念將 JDBC Connection 對象組織起來 它開始會有一些空置,而且已經鏈接好的數據庫鏈接,因此請求時 無須再創建和驗證,省去了新的鏈接實例時所必需的初始化和認證時間。它還控制最大鏈接數,避免過多的鏈接致使系統瓶頸。 除了 UNPOOLED 下的屬性外,會有更多屬性用來配置 POOLED 的數據源: • poolMax mumActiveConnections 是在任意時間都存在的活動( 也就是正在使用)鏈接數量,默認值爲 10 • poolMax murnldleConnections 是任意時間可能存在的空閒鏈接數。 • poolMaximumCheckoutTime 在被強制返回以前,池中鏈接被檢出( checked out )的時間,默認值爲20000 毫秒( 20 秒)。 • poolTimeToWait 個底層設置,若是獲取鏈接花費至關長的時間,它會給鏈接池打印狀態日誌 並從新嘗試獲取 個鏈接(避免在誤配置的狀況下一直失敗,默認值爲 20 000 毫秒(即 20 秒)。 • poolPingQuery 發送到數據庫的偵測查詢,用來檢驗鏈接是否 在正常工做秩序,並準備接受請求。默認是「NO PING QUERY SET 」,這會致使多數數據庫驅動失敗時帶有一個恰當的錯誤消息。
• poolPingEnabled 爲是否啓用偵測查詢。若開啓,也必須使用一個可執行的 SQL句設置 poo!PingQuery 屬性(最好是 個很是快的 SQL) ,默認值爲 false • poo!PingConnectionsNotUsedFor 爲配置 poo!PingQuery 使用頻度。這能夠被設置匹配具體的數據庫鏈接超時時間,來避免沒必要要的偵測,默認值爲 0即全部鏈接每一時刻都被偵測一一僅 poo!PingEnabled爲true 適用。
11.1 導入依賴
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>最新版本</version> </dependency>
11.2 配置
在 MyBatis 配置 xml 中配置攔截器插件
<plugins> <!-- com.github.pagehelper爲PageHelper類所在包名 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 使用下面的方式配置參數,後面會有全部的參數介紹 --> <property name="param1" value="value1"/> </plugin> </plugins>
在 Spring 配置文件中配置攔截
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注意其餘配置 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <!--使用下面的方式配置參數,一行配置一個 --> <value> params=value1 </value> </property> </bean> </array> </property> </bean>
分頁插件參數介紹
1. helperDialect :分頁插件會自動檢測當前的數據庫連接,自動選擇合適的分頁方式。 你能夠配置
helperDialect 屬性來指定分頁插件使用哪一種方言。配置時,可使用下面的縮寫值:
oracle , mysql , mariadb , sqlite , hsqldb , postgresql , db2 , sqlserver , informix , h2 , sqlserver201
2 , derby
特別注意:使用 SqlServer2012 數據庫時,須要手動指定爲 sqlserver2012 ,不然會使用 SqlServer2005 的
方式進行分頁。
你也能夠實現 AbstractHelperDialect ,而後配置該屬性爲實現類的全限定名稱便可使用自定義的實現方
法。
2. offsetAsPageNum :默認值爲 false ,該參數對使用 RowBounds 做爲分頁參數時有效。 當該參數設置爲
true 時,會將 RowBounds 中的 offset 參數當成 pageNum 使用,能夠用頁碼和頁面大小兩個參數進行分
頁。
3. rowBoundsWithCount :默認值爲 false ,該參數對使用 RowBounds 做爲分頁參數時有效。 當該參數設置
爲 true 時,使用 RowBounds 分頁會進行 count 查詢。
4. pageSizeZero :默認值爲 false ,當該參數設置爲 true 時,若是 pageSize=0 或者 RowBounds.limit =
0 就會查詢出所有的結果(至關於沒有執行分頁查詢,可是返回結果仍然是 Page 類型)。
5. reasonable :分頁合理化參數,默認值爲 false 。當該參數設置爲 true 時, pageNum<=0 時會查詢第一
頁, pageNum>pages (超過總數時),會查詢最後一頁。默認 false 時,直接根據參數進行查詢。
6. params :爲了支持 startPage(Object params) 方法,增長了該參數來配置參數映射,用於從對象中根據屬
性名取值, 能夠配置 pageNum,pageSize,count,pageSizeZero,reasonable ,不配置映射的用默認值, 默認
值爲
pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
。
7. supportMethodsArguments :支持經過 Mapper 接口參數來傳遞分頁參數,默認值 false ,分頁插件會從查
詢方法的參數值中,自動根據上面 params 配置的字段中取值,查找到合適的值時就會自動分頁。 使用方法
能夠參考測試代碼中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和
ArgumentsObjTest 。
8. autoRuntimeDialect :默認值爲 false 。設置爲 true 時,容許在運行時根據多數據源自動識別對應方言
的分頁 (不支持自動選擇 sqlserver2012 ,只能使用 sqlserver ),用法和注意事項參考下面的場景五。
9. closeConn :默認值爲 true 。當使用運行時動態數據源或沒有設置 helperDialect 屬性自動獲取數據庫類
型時,會自動獲取一個數據庫鏈接, 經過該屬性來設置是否關閉獲取的這個鏈接,默認 true 關閉,設置爲
false 後,不會關閉獲取的鏈接,這個參數的設置要根據本身選擇的數據源來決定。
PageHelper.startPage 靜態方法調用(重點)
這種方式是咱們要掌握的 在你須要進行分頁的 MyBatis 查詢方法前調用PageHelper.startPage 靜態方法便可,緊 跟在這個方法後的第一個MyBatis 查詢方法會被進行分頁
//獲取第1頁,10條內容,默認查詢總數
countPageHelper.startPage(1, 10)
//緊跟着的第一個select方法會被分頁
List<Country> list = countryMapper.selectIf(1)
動態 SQL 之<where>
<!-- 根據用戶信息查詢 --> <select id="findByUser" resultType="user" parameterType="user"> <include refid="defaultSql"></include> <where> <if test="username!=null and username != '' ">and username like #{username}</if> <if test="address != null">and address like #{address}</if> </where> </select>
動態標籤之<foreach>標籤
public class QueryVo implements Serializable { private List<Integer> ids; } List<User> findInIds(QueryVo vo); <!-- 查詢全部用戶在 id 的集合之中 --> <select id="findInIds" resultType="user" parameterType="queryvo"> <!-- select * from user where id in (1,2,3,4,5); --> <include refid="defaultSql"></include> <where> <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">#{uid} </foreach> </if> </where> </select>
SQL 語句:select 字段 from user where id in (?)<foreach>標籤用於遍歷集合,
它的屬性:collection:表明要遍歷的集合元素,注意編寫時不要寫#{}
open:表明語句的開始部分
close:表明結束
item:表明遍歷集合的每一個元素,生成的變量名
sperator:表明分隔符