主頁 > 軟體設計 > Java EE資料持久化框架 • 【第5章 MyBatis代碼生成器和快取配置】

Java EE資料持久化框架 • 【第5章 MyBatis代碼生成器和快取配置】

2021-04-29 14:06:20 軟體設計

全部章節 >>>>


本章目錄

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

標籤:其他

上一篇:演算法導論之經典演算法:快速排序全面決議

下一篇:前端框架入門必備100文章:vue、Element、vuetify、iview等

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more