全部章節 >>>>
本章目錄
4.1 MyBatis動
5.1 配置MyBatis Generator
5.1.1 MyBatis Generator介紹
5.1.2 MyBatis Generator XML檔案示例
5.1.3 MyBatis Generator XML詳解
5.1.3 <'context>標簽屬性
5.1.3 <'property>標簽
5.1.3 <'plugin>和<'commentGenerator>標簽
5.1.3 <'jdbcConnection>標簽
5.1.3 <'javaModelGenerator>標簽
5.1.3 <'javaClientGenerator>標簽
5.1.4 實踐練習
5.2 運行MyBatis Generator和Example
5.2.1 撰寫Java代碼運行MyBatis Generator
5.2.2 生成Example
5.2.3 實踐練習
5.3 MyBatis快取
5.3.1 MyBatis一級快取
5.3.2 MyBatis二級快取
5.3.3 使用MyBatis二級快取
5.3.4 實踐練習
5.4 MyBatis臟資料
5.4.1 MyBatis臟資料的產生
5.4.2 MyBatis臟資料的解決方案
5.4.3 實踐練習
總結:
5.1 配置MyBatis Generator
5.1.1 MyBatis Generator介紹
MyBatis在很大程度上大大降低了以前繁瑣的JDBC代碼,并且提供了大量的標簽對SQL陳述句的支持,但是在操作不同資料表方面,仍然存在大量重復作業,
MyBatis的開發團隊提供了一個很強大的代碼生成器——MyBatis Generator(MyBatis生成器,簡稱MBG)
MBG自動產生包含了資料庫表對應的物體類、Mapper介面類、Mapper XML檔案和Example物件等,這些代碼檔案中幾乎包含了全部的單表操作方法,
示例:要在MyBatis中使用MBG,首先需要在pom.xml中添加坐標依賴,如下:
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
版本號和mybatis關系不大
5.1.2 MyBatis Generator XML檔案示例
在專案的src/main/resources中創建一個generator目錄,在該目錄下創建一個generatorConfig.xml檔案,該組態檔主要針對MBG生成代碼時的一系列配置,如資料庫資訊、代碼位置配置等,該檔案內容核心結構如下:
示例:

<!-- 配置生成器 -->
<generatorConfiguration>
<!--
targetRuntime="MyBatis3Simple": 不會生成與Example相關的方法
targetRuntime="MyBatis3":默認值,生成基于MyBatis3.x以上版本的內容,包括XXXBySample
defaultModelType="flat":所有內容(主鍵,BLOB)等全部生成在一個物件中
defaultModelType="hierarchical":主鍵生成一個XXKey物件,BLOB等單獨生成一個物件,其他簡單屬性在一個物件中
defaultModelType="conditional"(默認值)表主鍵只有一列,不為該欄位生成單獨物體類,將該欄位合并到基本物體類中
-->
<context id="MySQLContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<!-- 配置前置分隔符和后置分隔符 -->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 配置注釋資訊 -->
<commentGenerator>
<!-- 不生成注釋 -->
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!-- 資料庫連接配置 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/dbauthority"
userId="root" password="root"></jdbcConnection>
<!-- targetPackage:生成物體類存放的包名, targetProject:指定目標專案路徑,可以使用相對路徑或絕對路徑 -->
<javaModelGenerator targetPackage="jack.mybatis.authority.model" targetProject="src\main\java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 配置SQL映射器Mapper.xml檔案的屬性 -->
<sqlMapGenerator targetPackage="jack.mybatis.authority.mapper" targetProject="src\main\resources"/>
<!-- type="XMLMAPPER":所有的方法都在XML中,介面呼叫依賴XML檔案 -->
<javaClientGenerator targetPackage="jack.mybatis.authority.mapper" type="XMLMAPPER"
targetProject="src\main\java"/>
<!-- 生成所有表的映射 -->
<table tableName="%">
<!-- 配置自增主鍵 -->
<generatedKey column="id" sqlStatement="MySQL" />
</table>
</context>
</generatorConfiguration>
5.1.3 MyBatis Generator XML詳解
<context>標簽
在MBG XML中至少配置1個<context>標簽,該標簽用于指定生成一組物件的環境,可配置多個,但是具體運行時選擇其中一個,
該標簽下的子標簽順序必須如下,否則報錯:
property(0個或多個),
plugin(0個或多個),
commentGenerator(0個或1個),
jdbcConnection(1個),
javaTypeResolver(0個或1個),
javaModelGenerator(1個),
sqlMapGenerator(0個或1個),
javaClientGenerator(0個或1個),
table(1個或多個),
5.1.3 <'context>標簽屬性
<context id=“自定義" targetRuntime="MyBatis3Simple" defaultModelType="flat">)
| 屬性名 | 取值 | 作用 |
| id | 自定義 | 唯一確定該標簽,運行時可以設定 |
|
defaultModelType 定義MBG如何生成物體類
| conditional(默認值) | 表主鍵只有一列,不為該欄位生成單獨物體類,將該欄位合并到基本物體類中 |
| flat(推薦) | 只為每張表生成一個物體類,這個物體類包含表中的所有欄位 | |
| hierarchical | 如果表有主鍵,那么該模型會產生一個單獨的主鍵物體類 | |
| targetRuntime 生成代碼的運行時環境 | MyBatis3 | 默認值 |
| MyBatis3Simple | 這種情況不會生成與Example相關的方法 |
5.1.3 <'property>標簽
<property>標簽
<property>標簽為屬性標簽,它定義一個全域意義的屬性及值,
| 屬性名 | 取值 |
| autoDelimitKeywords | 自動給關鍵字添加分隔符的屬性 |
| beginningDelimiter和endingDelimiter | 配置前置分隔符和后置分隔符的屬性,如果設定了前置分隔符和后置分隔符,那么,當資料庫的表名、欄位名中出現空格或關鍵字時,MyBatis將為這些名稱加上分隔符, |
5.1.3 <'plugin>和<'commentGenerator>標簽
<plugin>標簽
- <plugin>標簽用來定義一個插件,用于擴展或修改通過MBG生成的代碼,<plugin>標簽可以配置0個或者多個,個數不受限制,
<commentGenerator>標簽
- 用來配置如何生成注釋資訊,最多可以配置一個,常用的子標簽property屬性如下:
<commentGenerator>
<!--阻止生成注釋,默認為false-->
<property name="suppressAllComments" value="true" />
<!--阻止生成的注釋,包含時間戳,默認為false-->
<property name="suppressDate" value="true" />
<!--注釋是否添加資料庫表的備注資訊,默認為false-->
<property name="addRemarkComments" value="true" />
</commentGenerator>
5.1.3 <'jdbcConnection>標簽
<jdbcConnection>標簽
- 該標簽用于指定MBG要連接的資料庫資訊,該標簽必選,并且只能有一個,
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/db_authority"
userId="root" password="abc123">
</jdbcConnection>
<javaTypeResolver>標簽
- 該標簽的配置用來指定JDBC型別和Java型別如何轉換,最多可以配置一個,一般不配置, 默認即可,
5.1.3 <'javaModelGenerator>標簽
<javaModelGenerator>標簽
- 該標簽用來控制生成的物體類,targetPackage生成物體類存放的包名,targetProject指定目標專案路徑,
<javaModelGenerator targetPackage="jack.mybatis.authority.model“ targetProject="src\main\java">
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator>標簽
- 該標簽用于配置SQL映射器Mapper.xml檔案的屬性,該標簽可選,最多配置一個,如不配置則只產生物體類,不產生對應的Mapper.xml映射檔案,
<sqlMapGenerator targetPackage="jack.mybatis.authority.dao“ targetProject="src\main\resources" />
5.1.3 <'javaClientGenerator>標簽
<javaClientGenerator>標簽
- 該標簽用于配置Java客戶端生成器(Mapper介面)的屬性,該標簽可選,最多配置一個,如果不配置該標簽,就不會生成Mapper介面,
- 配置中的type屬性,推薦使用XMLMAPPER
<!--type="XMLMAPPER":所有的方法都在XML中,介面呼叫依賴XML檔案 -->
<!--如果type= ANNOTATEDMAPPER,則SQL生成在Mapper介面的注解中-->
<javaClientGenerator targetPackage="jack.mybatis.authority.dao" type="XMLMAPPER"
targetProject="src\main\java" />
<table>標簽
- <table>標簽用于配置需要通過映射的資料庫表,只有在<table>標簽中配置過的表,才能經過上述其他配置生成最終的代碼,<table>標簽至少要配置一個,可以配置多個,
- <table>標簽有一個必選屬性tableName,該屬性指定要生成的表名,可以使用SQL通配符匹配多個表,
例如,要生成全部的表,可以作如下配置:
<table tableName="%">
例如,要生成有關customer的表,可以作如下配置:
<table tableName="%customer%">
<generatedKey>標簽是<table>的子標簽
- 用來指定自動生成主鍵的屬性(identity欄位或者sequences序列),如果指定這個標簽,MBG將在生成insert的SQL映射檔案中插入一個<selectKey>標簽,這個標簽非常重要,而且只能配置一個,
- (1)column屬性:生成列的列名,
- (2)sqlStatement屬性:根據不同資料庫定義,mysql則定義為MySQL,
<table tableName= “%" >
<generatedKey column ="id " sqlStatement= "MySQL" />
</table>
5.1.4 實踐練習
5.2 運行MyBatis Generator和Example
MBG提供了很多種運行方式,常用的有以下幾種:
- 使用Java撰寫代碼運行,
- 從命令提示符運行,
- 使用Maven Plugin運行,
- 使用Eclipse插件運行,
使用Java編碼方式運行的好處是,generatorConfig.xml中配置的一些特殊的類(如<commentGenerator>標簽中type屬性配置的定制化的實作類)只要在當前專案中,或者在當前專案的classpath中,就可以直接使用,
5.2.1 撰寫Java代碼運行MyBatis Generator
如何撰寫代碼運行MyBatis Generator生成物體類、介面和Mapper映射檔案
保證專案中已經添加了mybatis-generator-core.jar依賴
在專案的src/main/java目錄下新建jack.mybatis.blog.generator包(包名可自定)
在改包下新建Generator.java類,包含main方法(注:該類代碼無需掌握)
public class Generator {
// targetRuntime="MyBatis3Simple", 不生成Example
public void generateMyBatis() {
List<String> warnings = new ArrayList<String>();//該集合記錄MBG執行程序中的警告資訊
boolean overwrite = true ; //當生成的代碼重復時,覆寫原代碼
String generatorFile = “/generator/generatorConfig.xml”; //指定組態檔路徑
InputStream is = Generator.class.getResourceAsStream(generatorFile);//讀取MBG組態檔
ConfigurationParser cp = new ConfigurationParser(warnings);
try {
Configuration config = cp.parseConfiguration(is);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings) myBatisGenerator.generate(null);//執行生成代碼
}
catch (Exception e) {
e.printStackTrace();
}
//列印出執行程序中的警告資訊,以便于修改
for (String warning : warnings) {
System.out.println(warning);
}
}
//main方法為java普通類運行入口
public static void main(String[] args) {
Generator generator = new Generator();
generator.generateMyBatis();
}
}
5.2.2 生成Example
- 在MBG的組態檔中,如果將targetRuntime屬性值設定為MyBatis3,則在生成MyBatis物體類的同時,還生成與之對應的帶Example的輔助查詢工具類,
- Example類包含了增加、修改、洗掉,以及查詢時動態構建的where子句,表中的每個非BLOB列可以被包括在where子句中,Example類可以用來生成一個幾乎無限的where子句,方便測驗和后期使用,
- 比如,與物體類SysUser對應的Example類為SysUserExample,它包含了常見的CRUD等方法的代碼示例,
實作一個用戶管理高級查詢功能,根據輸入的條件去檢索用戶資訊,這個功能還需要支持以下四種情況:
- 當只輸入用戶名關鍵字時,需要根據用戶名關鍵字進行模糊查詢,
- 當只一個日期時,需要獲取創建時間在該日期(含)之后的用戶資訊,
- 當同時輸入用戶名關鍵字和日期時,用這兩個條件去查詢匹配的用戶,
- 如果用戶名關鍵字和日期都沒有輸入,則查詢全部用戶資訊,
通過MGB已逆向生成了所有表所對應的物體類、Mapper介面,并且還生成Example類,現在只需定義一個測驗方法來實作上述需求,代碼如下:
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
SysUserExample userExample = new SysUserExample(); // 創建Example物件
SysUserExample.Criteria userCriteria = userExample.createCriteria(); // 創建查詢條件
if(!keyUserName.isEmpty())
// 設定根據用戶名關鍵字檢索的查詢條件
userCriteria.andUserNameLike('%'+keyUserName+'%');
if(!createTimeStr.isEmpty()) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date createTime = formatter.parse(createTimeStr);
// 設定根據時間檢索的查詢條件
userCriteria.andCreateTimeGreaterThanOrEqualTo(createTime);
}
// 執行查詢
List<SysUser> users = userMapper.selectByExample(userExample);
System.out.println("用戶數量:"+users.size());
updateByExample()方法和updateByExampleSelective()方法都可以實作更新,區別是當物件的屬性為空時,第一個方法會將值更新為null,第二個方法不會更新null屬性的欄位,
更新id在3至7范圍的用戶的密碼為999999,采用UserMapper的updateByExampleSelective()方法實作以上需求:
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
SysUserExample userExample = new SysUserExample();
SysUserExample.Criteria userCriteria = userExample.createCriteria();
// 更新條件:用戶id在3~7的范圍
userCriteria.andIdBetween(3L, 7L);
// 創建一個要設定的物件
SysUser user = new SysUser();
// 將密碼設定為999999
user.setUserPassword("999999");
// 執行查詢
int result = userMapper.updateByExampleSelective(user, userExample);
sqlSession.commit();
System.out.println("更新了"+result+"個用戶");
相信大家對Example應該己經有所了解,使用Example查詢能解決大部分復雜的單表操作,從一定程度上能減少作業量,但是建議在條件很多并且判斷很多的情況下,避免使用Example查詢,因為生成的代碼畢竟不是特別人性化,在這種情況下,根據需要自己去完善Mapper XML方式會更有效,
5.2.3 實踐練習
5.3 MyBatis快取
使用快取可以使應用更快地獲取資料,避免頻繁的資料庫互動,尤其是在查詢越多、快取命中率越高的情況下,使用快取的作用就越明顯,
快取的應用在企業級開發中隨處可見,合理的使用快取能大大提高專案的性能,因為快取的資料一般是在記憶體中,可以降低對資料庫的訪問次數,
MyBatis作為持久化框架,提供了非常強大的查詢快取特性,可以非常方便地配置和定制使用,MyBatis提供了一級快取和二級快取,其中一級快取默認啟用,不能控制,所以一般提到的快取,是指二級快取(可配置),
5.3.1 MyBatis一級快取
一級快取是MyBatis默認開啟且無法控制的快取,是屬于SqlSession級別,目的是提高查詢結果的利用率,在同一個SqlSession實體下進行查詢,會使用到一級快取,而不同的SqlSession實體則不會使用,
SqlSession sqlSession = getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查詢id為1L的用戶
SysUser user1 = userMapper.selectUserById(1L);
// 更新之前userName的值為admin
System.out.println("更新之前,user1的userName="+user1.getUserName());
// 更新user1的userName
user1.setUserName("new_admin");
// 再次獲取id為1L的用戶
SysUser user2 = userMapper.selectUserById(1L);
// 雖然沒有更新資料庫,但是user2的userName的值和user1重新賦值的名字相同,
// 它們都是new_admin
System.out.println("user2的userName="+user2.getUserName());
// 由于從一級快取中存在鍵值selectUserById(1L),因此user1和user2是同一個實體
System.out.println("user1==user2:"+(user1==user2));

示例:
重新開啟一個新的SqlSession實體,再次查詢該資料:
System.out.println("開啟新的SqlSession");
sqlSession = getSqlSession(); // 開啟一個新的SqlSession
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查詢id為1L的用戶
SysUser user2 = userMapper.selectUserById(1L);
// 第二個SqlSession獲取的的userName的值是admin
System.out.println("user2的userName="+user2.getUserName());
// 這里的user2和前一個SqlSession查詢的結果是兩個不同的實體
System.out.println("user1==user2:"+(user1==user2));
// 執行洗掉操作(或者新增、更新操作),將清空一級快取
userMapper.deleteUserById(10L);
sqlSession.commit();
// 再次查詢id為1L的用戶
SysUser user3 = userMapper.selectUserById(1L);
System.out.println("user3的userName="+user3.getUserName());
// 由于將清空了一級快取,因此user2和user3不是同一個實體
System.out.println("user2==user3:"+(user2==user3));
User2和剛才的user1雖然資料一樣,但是不是同一個物件,列印false
執行洗掉操作后,一級快取會被清除,所以查詢的user3和user2也不是同一個物件,列印false
1)在同一個SqlSession下進行的查詢操作,查詢的結果會默認放入一級快取中,再次查詢時會到一級快取中去尋找是否存在該資料,如果存在則取出,而不查詢資料庫;如果不存在,則再去查找資料庫,并且放入一級快取中,當然在SqlSession下進行任何的新增、更新和洗掉操作都會清空一級快取,以保證資料的準確性,
2)如果希望某個查詢操作不使用一級快取,則可以在配置時進行如下設定:
<!--清空當前一級快取-->
<select id="selectUserById" resultMap="userMap" flushCache="true">
select * from sys_user where id=#{id}
</select>
配置為true后,會在查詢資料前清空當前的一級快取,一般不建議設定
5.3.2 MyBatis二級快取
MyBatis二級快取是Mapper級別的快取,每一個Mapper都有一個二級快取區域(按namespace區分)
如果兩個Mapper的namespace相同,則這兩個Mapper執行SQL查詢所得到的資料將存在相同的二級快取區域中,即多個SqlSession可能共用二級快取,
MyBatis的全域配置settings中有一個引數cacheEnabled,該引數是二級快取的全域開關,在mybatis核心主配置中可以添加配置,如下:
<!--mybatis全域核心配置中-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在保證二級快取的全域配置開啟的情況下,不同Mapper下的二級快取需要設定開啟,有兩種不同的方式進行Mapper命名空間快取啟用方式,
使用Mapper.xml開啟二級快取只需要在介面對應的Mapper.xml中添加<cache/>元素即可,如下:
<!--UserMapper.xml組態檔-->
<mapper namespace="jack.mybatis.authority.mapper.UserMapper">
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="false“ />
<!--其他配置-->
</mapper>
namespace為命名空間區域
可通過屬性配置二級快取特性
使用介面中注解方式配置映射時,開啟該命名空間下二級快取的方式,如下:
import org.apache.ibatis.annotations.CacheNamespace;
@CacheNamespace(
eviction=FifoCache.class,
flushInterval=60000,
size=512,
readWrite=true
)
public interface UserMapper{
// 介面方法
}
二級快取配置屬性引數說明:
| 屬性名 | 取值 | 作用 |
|
eviction (回收策略) | LRU(默認值) | 移除最長時間不被使用的物件,這是默認值 |
| FIFO | 按物件進入快取的順序來移除它們 | |
| SOFT | 移除基于垃圾回收器狀態和軟參考規則的物件 | |
| WEAK | 更積極地移除基于垃圾收集器狀態和弱參考規則的物件 | |
| flushinterval (重繪間隔) | 可以被設定為任意的正整數,而且它們代表一個合理的毫秒形式的時間段,默認情況不設定,即沒有重繪間隔,快取僅僅在呼叫陳述句時重繪 | |
| size(參考數目) | 可以被設定為任意正整數,默認值是1024 | |
| readOnly(只讀) | 可設定為true或false,只讀的快取所有呼叫者回傳快取物件的相同實體,這些物件不能被修改;可讀寫快取會通過序列化回傳快取物件的拷貝,這種方式慢一些,但是安全,因此默認值是false | |
默認的二級快取會有如下效果:
映射陳述句檔案中的所有select陳述句將會被快取,
映射陳述句檔案中的所有insert、update和delete陳述句會重繪快取,
快取會使用Least Recently Used(LRU,最近最少使用)演算法來識訓,
如果沒有設定重繪時間間隔,快取不會以任何時間順序來重繪,
默認情況下不能同時使用Mapper.xml和介面兩種方式都開啟二級快取,會出現配置沖突,所以一般使用一種配置方式即可,最好不要混用,
5.3.3 使用MyBatis二級快取
如對UserMapper配置二級快取后,當呼叫UserMapper所有的select查詢方法時,二級快取就己經開始起作用,在使用可讀寫快取時,要求快取的物體類需要實作序列化介面,如SysUser物體類:
public class SysUser implements Serializable{
// 其他屬性和getter()方法、setter()方法
}
呼叫UserMapper中的查詢方法測驗快取:
sqlSession = getSqlSession(); // 開啟一個新的SqlSession
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 第二個SqlSession獲取的的userName的值是從二級快取取得,因此是new_admin
SysUser user2 = userMapper.selectUserById(1L);
// 由于二級快取配置為讀寫快取,user1和user2是兩個不同的實體
System.out.println("user1==user2:"+(user1==user2));
SysUser user3 = userMapper.selectUserById(1L);// 這里仍然從二級快取中取出
// user2和user3都是2級別快取讀取出來的結果,但是為false
System.out.println("user2==user3:"+(user2==user3));
因為二級讀寫快取是反序列化的結果,所以為false
5.3.4 實踐練習
5.4 MyBatis臟資料
5.4.1 MyBatis臟資料的產生
二級快取雖然能提高應用效率,減輕資料庫服務器的壓力,但是如果使用不當,很容易產生臟資料,
MyBatis的二級快取和命名空間系結的,每個Mapper命名空間下的二級快取互不影響,但是難免遇到一個命名空間所快取的資料,在資料庫中已被其他命名空間修改,快取的資料則不是資料庫最真實的,即臟資料,
通過案例來演示臟資料的產生:
示例:在UserMapper中創建了selectUserAndRoleById()方法,該方法獲取指定用戶id的用戶資訊,用戶資訊要求包含該用戶所對應的角色資訊
<!—添加開啟當前UserMapper空間下二級快取配置-->
<cache eviction="FIFO“ flushInterval="60000“ size="512“ readOnly="false"/>
<select id="selectUserAndRoleById" resultType="SysUser">
select u.id, u.user_name, u.user_email, u.user_info, u.head_img, u.create_time,
r.id "role.id", r.role_name "role.roleName", r.enabled "role.enabled",
r.create_by "role.createBy", r.create_time "role.createTime"
from sys_user u join sys_user_role ur on u.id=ur.user_id join sys_role r
on r.id=ur.role_id where u.id=#{userId}
</select>
該方法查詢的資料會被快取到UserMapper空間下的二級快取中
示例:在RoleMapper.xml添加二級快取配置,增加<cache/>元素,代碼如下
<cache
eviction="LRU"
flushInterval="10000"
size="1024"
readOnly="false"
/>
讓SysUser類實作Serializable介面
public class SysUser implements Serializable {
//相關屬性略
}
通過案例來演示臟資料的產生:
示例:在RoleMapper中創建了selectRoleById()方法,該方法獲取指定角色id的角色,另外,再創建updateRole()方法,該方法更新指定角色id的角色資訊
<resultMap id="roleMap2" type="SysRole">
<result property="id" column="id" />
<result property="roleName" column="role_name" />
<result property="enabled" column="enabled" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
</resultMap>
<select id="selectRoleById" resultMap="roleMap2">
select * from sys_role where id=#{id}
</select>
<update id="updateRole">
update sys_role set
role_name=#{roleName},enabled=#{enabled},create_by=#{createBy},
create_time=#{createTime,jdbcType=TIMESTAMP} where id=#{id}
</update>
RoleMapper下更新角色的資訊不會影響到UserMapper的二級快取
1、UserMapper空間下定義開啟二級快取,并且查詢方法會把用戶及角色資料快取至二級快取中,
2、RoleMapper中的修改方法呼叫后,不會影響到UserMapper空間下的二級快取,因為二級快取只在各自空間下有效,
3、所以UserMapper中二級快取中的資料并非資料庫中最新的資料,會造成資料不合理的臟資料,
5.4.2 MyBatis臟資料的解決方案
如何避免臟資料的出現?需要用到參照快取了,當某幾個表可以作為一個業務整體的查詢來源時,通常是讓幾個會關聯的資料表同時使用同一個二級快取,這樣就能解決臟資料問題,
將UserMapper.xml中的快取配置修改如下:
<mapper namespace="jack.mybatis.authority.mapper.UserMapper">
<cache-ref namespace="jack.mybatis.authority.mapper.RoleMapper"/>
<!—其他配置-->
</mapper>
參照快取可以解決關聯較少的情況,如果有幾十個表且關聯復雜時,使用參照快取意義不大,因此使用二級快取需要滿足一定的條件:
- 以查詢為主的應用中,只有盡可能少的新增、洗掉和更新操作,
- 查詢業務絕大多數都是對單表進行操作,由于很少存在互相關聯的情況,因此不會出現臟資料,
- 可以按業務劃分對表進行分組時,如果關聯的表比較少,可以通過參照快取進行配置,
5.4.3 實踐練習
總結:
- 利用MyBatisGenerator可以快速生成針對資料庫表的物體類、介面、Mapper.xml映射組態檔,以及Example輔助查詢工具類,
- 快取是一種將資料庫查詢的資料進行臨時存盤,一般是存盤在記憶體中,后續查詢時減少和資料庫的互動次數,提高程式性能的技術,
- MyBatis中提供了一級快取和二級快取,其中一級快取默認存在,不可控制,同一SqlSession范圍內的操作共享該快取,增、刪、改后將清除快取,
- 二級快取需要配置才能生效,屬于各自命名空間范圍的快取,在同一命名空間范圍內,即使不同SqlSession也可共用,使用時需要注意臟資料的產生,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/281305.html
標籤:其他
