MyBatis 實踐 --配置
來自: http://blog.csdn.net/zjf280441589/article/details/50760942
MyBatis 實踐
標簽: Java與存儲
Configuration
mybatis-configuration.xml是MyBatis的全局配置文件(文件名任意),其配置內容和順序如下:
- properties : 屬性(文件)加載/配置
- settings : 全局配置參數
- typeAliases : 定義類型別名
- typeHandlers : 類型處理器
- objectFactory : 對象工廠
- plugins : 插件
- environments : 環境集合屬性對象
- environment
- transactionManager : 事務管理
- dataSource : 數據源
- environment
- databaseIdProvider:P數據庫廠商標識
- mappers : 映射器
properties
方便對配置參數統一管理,供其他XML引用,我們可以將數據庫的連接參數抽取出來:
- db.properties
## Data Source mysql.driver.class=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://host:port/db?characterEncoding=utf-8 mysql.user=user mysql.password=password
- mybatis-configuration.xml
</ul>
<properties resource="db.properties"/><environments default="development"> <environment id="development"> <!-- 配置JDBC事務管理--> <transactionManager type="JDBC"/> <!-- 配置數據源--> <dataSource type="POOLED"> <property name="driver" value="${mysql.driver.class}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.user}"/> <property name="password" value="${mysql.password}"/> </dataSource> </environment> </environments></pre>
注: MyBatis按照如下順序加載properties:
1) 在<properties>
標簽內定義的屬性;
2) .properties文件中定義的屬性;
3) 最后讀取作為方法參數傳遞的屬性.</blockquote>
settings
MyBatis全局配置參數,會影響MyBatis運行時行為(如:開啟二級緩存/延遲加載).見MyBatis文檔.
typeAliases
MyBatis默認支持的類型別名可參考MyBatis文檔,我們也可以自定義別名,但并不推薦,使用PO對象的全限定名可以提高Statement的可讀性.
typeHandlers
typeHandlers
用于Java類型和JDBC類型轉換,MyBatis提供了很多默認的類型處理器(詳見MyBatis文檔),而且也基本滿足日常開發需求,因此一般就不再需要單獨定義.
mappers
前面已經將SQL語句定義到了mapper文件中,那么
<mappers/>
屬性就是告訴MyBatis到哪里去尋找mapper文件,MyBatis提供了如下幾種配置方法:
配置 描述 <mapper resource=""/>
使用類路徑的資源( Resources
/java
目錄下)<mapper url=""/>
使用完全限定路徑 <mapper class=""/>
使用mapper接口類路徑 <package name=""/>
注冊指定包下的所有mapper接口 注意:后兩種方式要求mapper接口名和mapper映射文件名稱相同,且放在同一個目錄中(不推薦).
其他關于MyBatis的配置信息可參考MyBatis文檔.
整合Spring
實現MyBatis與Spring整合之后,可以使用Spring來管理
SqlSessionFactory
和mapper接口,Spring自動使用SqlSessionFactory
創建SqlSession
,并將實現好DAO接口注冊到Spring容器中, 供@Autowired
使用.
1. 添加依賴
- 添加Spring支持
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency>
- 添加MyBatis-Spring包
</ul>
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring.version}</version> </dependency>
- 添加Hikaricp數據庫連接池
</ul>
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>${hikaricp.version}</version> </dependency>
- 不要忘了MySQL數據庫驅動
</ul>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency>
2. 配置文件
- 精簡mybatis-configuration.xml
可以將數據源的配置移到下面的applicationContext-datasource.xml中.<?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> <mappers> <mapper resource="mybatis/mapper/UserDAO.xml"/> </mappers> </configuration>
- 定義applicationContext-datasource.xml
</ul>
<beans xmlns="</beans></pre>
上面的配置存在一個問題:需要針對每個mapper配置一個
MapperFactoryBean
(繁瑣),因此這段根據mapper接口生成代理對象的配置可更改如下:<!-- 基于包掃描的mapper配置 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.fq.mybatis"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>附: applicationContext-database.xml完整配置可參考: Git地址
</blockquote>
- 定義Spring主配置文件applicationContext.xml
定義注解驅動及加載靜態配置文件datasource:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="</beans></pre>
- Client
</ul>
/* @author jifang @since 16/2/22 上午10:20. / @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring/applicationContext.xml") public class UserDAOClient {@Autowired private UserDAO dao; @Test public void client() throws Exception { User user = dao.selectUserById(1); System.out.println(user); }
}</pre>
緩存
與大多數持久層框架一樣,MyBatis也支持一級緩存和二級緩存.
緩存作用是提升系統整體性能(不是提升數據庫性能:因為緩存將數據庫中的數據存放到內存,下次查詢同樣內容時直接從內存讀取,減輕數據庫壓力,而且直接從內存中讀取數據要比從數據庫檢索快很多,因此可以提升系統整體性能).
緩存數據更新:當一個作用域(一級緩存為
SqlSession
/二級緩存為namespace)進行了C/U/D
操作后,默認該作用域下所有緩存都被清空.
一級緩存
MyBatis默認開啟了一級緩存.一級緩存是基于
org.apache.ibatis.cache.impl.PerpetualCache
的HashMap
本地緩存,其存儲作用域為SqlSession
,同一個SqlSession
幾次執行相同SQL,后面的查詢會直接從緩存中加載,從而提高查詢效率/減輕數據庫壓力.當SqlSession
經flush
/close
后,該SqlSession
中的所有Cache數據被清空.
二級緩存
與一級緩存機制類似,MyBatis二級緩存默認也是采用
PerpetualCache
的HashMap
存儲,不同在于二級緩存存儲作用域為namespace
/mapper
,并且可以自定義緩存實現,如Ehcache.MyBatis默認沒有開啟二級緩存,需要經過以下步驟才能使用:
- 啟用二級緩存(可選)
其需要在mybatis-configuration.xml的settings
全局參數中開啟:<settings> <setting name="cacheEnabled" value="true"/> </settings>
cacheEnabled
對此配置文件下的所有cache進行全局性開/關設置(默認為true
).</blockquote>
- 配置緩存策略
在mapper映射文件中添加<cache/>
標簽,以指定該namespace開啟二級緩存, 并指定緩存策略:<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>1)
eviction
:緩存淘汰算法:
算法 描述 釋義 LRU 最近最少使用 移除最長時間不被使用的對象(默認). FIFO 先進先出 按對象進入緩存的順序移除. SOFT 軟引用 移除基于垃圾回收器狀態和軟引用規則的對象. WEAK 弱引用 更積極地移除基于垃圾收集器狀態和弱引用規則的對象. 2)
flushInterval
:刷新間隔(緩存過期時間),單位為毫秒,MyBatis會每隔一段時間自動清空緩存(默認刷新間隔為空, 即永不過期,僅調用語句時刷新).
3)size
:引用數目,要記住你緩存的對象的數目和運行環境可用內存資源數目(默認1024).
4)readOnly
: 只讀.如果為true,則所有相同SQL返回同一對象(因此這些對象不能修改,有助于提高性能,但并發操作同一條數據時,可能不安全);如果為false,則相同SQL后面返回的是cache的clone副本(通過序列化,慢一些但更是安全,因此默認是false).
- 序列化
PO對象要實現Serializable
序列化,因為二級緩存的存儲介質不一定只是內存:public class User implements Serializable { //... }
- Client
</ul>
@Test public void cacheClient() throws Exception { testCache(factory.openSession()); testCache(factory.openSession()); testCache(factory.openSession()); }private void testCache(SqlSession session) throws Exception { UserDAO dao = session.getMapper(UserDAO.class); dao.selectUserById(1); // 需要將SqlSession關閉才能將數據寫入緩存. session.close(); }</pre>
運行代碼, 并觀察log輸出的命中率(Cache Hit Ratio).
- Statement配置
1) 禁用緩存: 在Statement中設置
useCache="false"
可以禁用當前select語句的二級緩存(默認為true
:該SQL啟用二級緩存).<select id="selectUserById" parameterType="java.lang.Integer" resultType="com.fq.domain.User" useCache="true"> SELECT * FROM user WHERE id = #{id}; </select>2)刷新緩存: 同一個namespace中,如果還有其它insert/update/delete操作,需要刷新緩存,使用
flushCache="true"
屬性設置(默認為true
刷新緩存).<insert id="insertUserList" parameterType="java.util.List" flushCache="true"> INSERT INTO user(name, password) VALUES <if test="list != null and list.size != 0"> <foreach collection="list" item="user" separator=","> (#{user.name}, #{user.password}) </foreach> </if> </insert>
整合Ehcache
MyBatis暴露一個
org.apache.ibatis.cache.Cache
接口出來,通過實現該接口,可以實現各類緩存產品(如Ehcache/Redis/Memcached)與MyBatis的整合(MyBatis的特長操作數據庫,緩存管理并不是其擅長,因此整合其他緩存產品可以提高系統整體性能).
Ehcache是一個純Java開發的進程內緩存框架,具有開源/快速/靈活等特點,是Hibernate默認的CacheProvider.使用Ehcache需要在pom.xml中添加如下依賴:<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.11</version> </dependency> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.3</version> </dependency>
- 配置Ehcache
在Resources目錄下添加ehcache.xml配置文件</ul>
<ehcache> <diskStore path="/data/cache"/> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
屬性 <th align="left">描述</th>
</tr>
</thead>
diskStore
<td align="left">指定緩存數據在磁盤的存儲位置</td>
</tr>
maxElementsInMemory
在內存中緩存element的最大數目 maxElementsOnDisk
在磁盤上緩存element的最大數目,0表示無窮大 eternal
設定緩存的elements是否永遠不過期.true,則緩存的數據始終有效,如果為false那么還要根據timeToIdleSeconds,timeToLiveSeconds判斷 overflowToDisk
設定當內存緩存溢出的時候是否將過期的element緩存到磁盤上 timeToIdleSeconds
刷新間隔:緩存數據前后兩次訪問時間超過timeToIdleSeconds時,這些數據便會刪除(默認為0,時間間隔無窮大) timeToLiveSeconds
緩存element的有效生命期(默認為0,時間無限) diskSpoolBufferSizeMB
設置DiskStore(磁盤緩存)緩存區大小.默認是30MB. diskPersistent
在JVM重啟時是否使用磁盤保存Ehcache數據,默認是false. diskExpiryThreadIntervalSeconds
磁盤緩存的清理線程運行間隔,默認是120秒. memoryStoreEvictionPolicy
當內存緩存達到最大,有新的element加入的時候, 移除緩存中element的策略.默認是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出) </tbody> </table>
- mapper配置ehcache
<cache type="org.mybatis.caches.ehcache.EhcacheCache" eviction="LRU" flushInterval="60000" size="1024" readOnly="true"/>還可以根據需求調整當前namespace的緩存參數:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"> <property name="timeToIdleSeconds" value="3600"/> <property name="timeToLiveSeconds" value="3600"/> <!-- 同ehcache參數maxElementsInMemory --> <property name="maxEntriesLocalHeap" value="1000"/> <!-- 同ehcache參數maxElementsOnDisk --> <property name="maxEntriesLocalDisk" value="10000000"/> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
二級緩存小結
- 適用場景
對于查詢請求多且對查詢結果實時性要求不高的場景,可采用二級緩存降低數據庫負擔,提高訪問速度(業務場景如:微博/動態/訂單信息等).- 局限
二級緩存對細粒度級別的緩存實現不好,如”緩存所有的商品信息時,二級緩存就無法實現當一個商品信息變化時只刷新該商品緩存而不刷新全部商品緩存“,因為二級緩存區域以namespace
為單位劃分,當一個商品發生變化會將所有商品緩存清空,因此解決此類問題需要在上層對數據進行業務劃分.</ul> </div>
本文由用戶 TerenceMort 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關經驗
相關資訊
sesese色