關於Mybatis與Spring整合以後SqlSession與mapper對象之間數量的問題。

1,sqlsession的真實類型和數量

因爲使用spring管理bean,當咱們在代碼中須要使用這個bean的時候,會首先去容器中找,第一次須要調用MapperFactoryBean的getObject方法獲取一個bean,並保存到容器中。spring

MapperFactoryBean的getObject方法以下:sql

 

因爲每一個MapperFactoryBean對象初始化的時候,都會建立一個sqlSession,代碼在MapperFactoryBean類的父類SqlSessionDaoSupport中,當spring向MapperFactoryBean對象中注入SqlSessionFactory時就建立了SqlSession:數據庫

 

【結論1】:一個MapperFactoryBean對象擁有一個sqlSession對象。類型是org.mybatis.spring.SqlSessionTemplate緩存

重要:spring整合mybatis使用的sqlSession類型是org.mybatis.spring.SqlSessionTemplatesession

那麼整合後的mybatis是怎麼執行的呢?mybatis

首先查看SqlSessionTemplate類能夠看到,全部的數據庫執行都被一個動態代理的sqlsession對象代理了。app

 

在構造方法中查看該代理對象的構造spa

使用JDK動態代理,實現InvocationHandler的類是SqlSessionIntercepteor,查看它的invoke方法以下:3d

 

能夠看到,方法開始就直接建立了一個新的sqlsession對象,這個對象就是被代理的對象。代理

再看getSqlSession方法,它是SqlSessionUtils中的一個靜態方法,以下:

 

第一句話和事務有關,若是它返回空,則直接使用sessionFactory建立一個新的session

【結論】spring整合mybatis後,非事務環境下,每次操做數據庫都使用新的sqlSession對象。所以mybatis的一級緩存沒法使用(一級緩存針對同一個sqlsession有效)

下面兩段代碼:

(1)不整合spring,以下代碼的輸出能夠看出,使用了一級緩存

 

結果:查詢過程只執行了一次。

 

(2)整合spring,

 

輸出結果以下:

 

兩次的輸出表示沒有使用一級緩存。

2,Mapper接口對應的bean在容器中的數量

經過getObject返回的對象是單利的,從MapperFactoryBean的isSingleton()能夠得出

 

【結論二】所以,同一個IOC容器中同一個Mapper接口對應的代理類只有一個

例如系統有一個UserMapper接口對應UserMapper.xml

則以下代碼返回true

 

相關文章
相關標籤/搜索