MyBatis中的緩存
Mybatis作為持久化框架,提供了非常強大的緩存特性。一般在提到Mybatis緩存的時候,指的都是二級緩存。一級緩存,即本地緩存,默認會啟用並且不能控制,可能會導致一些難以發現的錯誤。
一、一級緩存
[java] view plain copy
public
void
testL1Cache() {- SqlSession sqlSession = getSqlSession();
- SysUser user1 =
null
; try
{
- UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
); - user1 = userMapper.selectById(1L);
- user1.setUserName("New Name");
- SysUser user2 = userMapper.selectById(1L);
- // 雖然沒有更新資料庫,但是這個用戶名和user1重新複製的名字相同
- Assert.assertEquals("New Name", user2.getUserName());
- // 無論如何,user2和user1完全就是同一個實例
- Assert.assertEquals(user1, user2);
- }
finally
{ - sqlSession.close();
- }
- System.out.println("開啟新的sqlSession");
- sqlSession = getSqlSession();
try
{- UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
); - SysUser user2 = userMapper.selectById(1L);
- Assert.assertNotSame("New Name", user2.getUserName());
- Assert.assertNotSame(user1, user2);
- // 執行刪除操作
- userMapper.deleteById(2L);
- //獲取user3
- SysUser user3 = userMapper.selectById(1L);
- Assert.assertNotSame(user3, user2);
- }
finally
{
- sqlSession.close();
- }
- }
在如上的測試代碼中,獲取到user1之後,重新設置了username的值,但並未更新到資料庫中;當再次執行該對象的查詢之後,發現得到的user2對象的username屬性和user1之前重新設置的值一樣,並且此時user1和user2是同一個對象。這就是一級緩存導致的。
Mybatis的一級緩存存在於SqlSession的生命周期當中,意思就是說,在同一個SqlSession中執行的查詢操作,且中間不包括增刪改的操作時,如果該對象在之前已經查詢過,新查詢獲取到的都將是保存在緩存中的這個對象。當二級緩存沒有開啟時,我們重新開啟一個SqlSession,這時再查詢,就不再是之前的緩存的那個對象了。這是因為在SqlSession關閉時,緩存已經被清空了。
如果不想讓該方法使用一級緩存,可以在該方法的xml文件中增加 flushCache="true" 的屬性。這樣配置之後,在該方法的每次查詢之前都會清空當前的一級緩存,重新從資料庫中查詢對象,可以避免上面的問題。但是這個方法由於清空了一級緩存,會影響當前SqlSession緩存的所有查詢,會增加資料庫的查詢次數,導致性能的下降。
二、二級緩存
不同於一級緩存,二級緩存的生命周期可以理解為SqlSessionFactory的生命周期。二級緩存的相關配置在這裡就不敘述了。需要注意的是,xml配置方式和註解配置方式不能同時使用,會因為命名空間的衝突而導致異常,可以將其中一個改為參照緩存即可。
[java] view plain copy
public
void
testL2Cache(){- SqlSession sqlSession = getSqlSession();
- SysRole role1 =
null
;
try
{- RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.
class
); - role1 = roleMapper.selectById(1L);
- role1.setRoleName("New Name");
- SysRole role2 = roleMapper.selectById(1L);
- Assert.assertEquals("New Name", role2.getRoleName());
- Assert.assertEquals(role1, role2);
- }
finally
{ - sqlSession.close();
- }
- System.out.println("開啟新的SqlSession");
try
{- sqlSession = getSqlSession();
- RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.
class
); - SysRole role2 = roleMapper.selectById(1L);
- Assert.assertEquals("New Name", role2.getRoleName());
- Assert.assertNotEquals(role1, role2);
- SysRole role3 = roleMapper.selectById(1L);
- Assert.assertNotEquals(role3, role2);
- }
finally
{ - sqlSession.close();
- }
- }
上面的測試代碼中,再次獲取role2時,即使已經在一個新的SqlSession當中,一級緩存已經清空,role2並不會執行資料庫的查詢操作,而是到Mybatis的二級緩存中取出對象,此時role2的rolename屬性為之前修改後的值。由於在本測試用例中,配置的二級緩存屬性為可讀寫緩存,role2和role3都是反序列化的介面,所以他們並不是相同的實例。如果配置為只讀緩存,role2和role3獲得的將是緩存中role1的引用,將會是相同的實例。
目前,mybatis支持EhCache緩存框架以及Redis緩存資料庫來保存mybatis的二級緩存。
※主機 電子郵件訪問
※AppML Products 之完整的應用程序
TAG:程序員小新人學習 |