知識點:spring 集成myBatisjava
基礎集成使用: 一、配置 SqlSessionFactoryBeanspring
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
複製代碼
二、配置 MapperFactoryBeansql
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.niuh.mybatis.dao.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
複製代碼
三、獲取mapper 對像執行業務方法apache
context = new ClassPathXmlApplicationContext("spring.xml");
UserMapper mapper = context.getBean(UserMapper.class);
System.out.println(mapper.selectByid(1));
複製代碼
對像說明: FactoryBean: 工廠Bean 用於 自定義生成Bean對像,當在ioc 中配置FactoryBean 的實例時,最終經過bean id 對應的是FactoryBean.getObject()實例,而非FactoryBean 實例自己 SqlSessionFactoryBean: 生成SqlSessionFactory 實例,該爲單例對像,做用於整個應用生命週期。經常使用屬性以下:緩存
MapperFactoryBean: 生成對應的Mapper對像,一般爲單例,做用於整個應用生命週期。經常使用屬性以下:安全
關於Mapper 單例狀況下是否存在線程安全的問題? 在原生的myBatis 使用中mapper 對像的生命期是與SqlSession同步的,不會存在線程安全問題,如今單例的mapper 是如何解決線程安全的問題的呢?bash
SQL Session 集成結構: session
初始化流程 // 建立 會話模板 SqlSessionTemplatemybatis
>org.mybatis.spring.mapper.MapperFactoryBean#MapperFactoryBean()
>org.mybatis.spring.support.SqlSessionDaoSupport#setSqlSessionFactory
>org.mybatis.spring.SqlSessionTemplate#SqlSessionTemplate()
>org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor
複製代碼
// 建立接口app
>org.mybatis.spring.mapper.MapperFactoryBean#getObject
>org.mybatis.spring.SqlSessionTemplate#getMapper
>org.apache.ibatis.session.Configuration#getMapper
複製代碼
// 執行查詢
>com.niuh.mybatis.dao.UserMapper#selectByid
>org.apache.ibatis.binding.MapperProxy#invoke
>org.mybatis.spring.SqlSessionTemplate#selectOne(java.lang.String)
>org.mybatis.spring.SqlSessionTemplate#sqlSessionProxy#selectOne(java.lang.String)
>org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
>org.mybatis.spring.SqlSessionUtils#getSqlSession()
>org.apache.ibatis.session.SqlSessionFactory#openSession()
>org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne()
複製代碼
每次查詢都會建立一個新的 SqlSession 會話,一級緩存還會生效嗎? 以前瞭解到 一級緩存的條件是必須相同的會話,因此緩存經過和spring 集成以後就不會生效了。除非使用spring 事物 這時就不會在從新建立會話。
spring 事物沒有針對myBatis的配置,都是一些常規事物配置:
<!--添加事物配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
<!--事物註解配置-->
<tx:annotation-driven/>
複製代碼
添加事物註解:
@Transactional()
public User getUser2(Integer id) {
userMapper.selectByid(id);
return userMapper.selectByid(id);
}
複製代碼
執行測試發現 當調用getUser2 方法時兩次查詢不在重複建立 sqlSession。而是共用一個直到getUser2 方法結束。
事物與SqlSession 集成原理: 其原理前面講查詢流程時有所涉及。每次執行SQL操做前都會經過 getSqlSession 來獲取會話。其主要邏輯是 若是當前線程存在事物,而且存在相關會話,就從ThreadLocal中取出 。若是沒就從建立一個 SqlSession 並存儲到ThreadLocal 當中,共下次查詢使用。 相關源碼:
>org.mybatis.spring.SqlSessionUtils#getSqlSession()
>org.springframework.transaction.support.TransactionSynchronizationManager#getResource
>org.mybatis.spring.SqlSessionUtils#sessionHolder
>org.apache.ibatis.session.SqlSessionFactory#openSession()
>org.mybatis.spring.SqlSessionUtils#registerSessionHolder
>org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive
>org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
複製代碼
若是每一個mapper 接口都配置*MapperFactoryBean *至關麻煩 能夠經過 以下配置進行自動掃描
<mybatis:scan base-package="com.niuh.mybatis.dao"/>
複製代碼
其與 spring bean 註解掃描機制相似,因此得加上註解掃描開關的配置
<context:annotation-config/>
複製代碼