在項(xiàng)目中原始的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"
default-autowire="byName">
<bean id="baseDataSource" class="org.apache.commons.dbcp.BasicDataSource" abstract="true" destroy-method="close" lazy-init="true">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="30" />
<property name="initialSize" value="3" />
<property name="timeBetweenEvictionRunsMillis" value="290000" />
<property name="minEvictableIdleTimeMillis" value="290000" />
<property name="numTestsPerEvictionRun" value="20" />
</bean>
<!-- DBCP config -->
<bean id="targetDataSource" parent="baseDataSource" lazy-init="true">
<property name="url" value="${master.jdbc.url}" />
</bean>
<bean id="slaveDataSource" parent="baseDataSource" lazy-init="true">
<property name="url" value="${slave.jdbc.url}"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="targetDataSource" />
</bean>
<bean id="dataSourceSlave" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="slaveDataSource"/>
</bean>
<bean id="dataSource" class="com.jd.gx.dao.utils.DynamicDataSource">
<property name="targetDataSources">
<util:map key-type="java.lang.String">
<entry key="master" value-ref="dataSource" />
<entry key="slave" value-ref="dataSourceSlave"/>
</util:map>
</property>
<property name="defaultTargetDataSource" ref="dataSource" />
<!--<property name="dbInUse" value="master" />-->
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:pointcut id="txServiceMethods" expression="execution(* com.*.service..*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txServiceMethods" />
</aop:config>
<!-- mybatis config -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
<property name="mapperLocations" value="classpath*:sqlmap/**/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="selectDbAdvice" class="com.test.dao.utils.DbSelectAdvice">
<property name="methodKey">
<list>
<value>count</value>
<value>select</value>
</list>
</property>
<property name="showLog" value="false"/>
</bean>
<aop:aspectj-autoproxy/>
<aop:config>
<aop:pointcut expression="execution(* com.test.dao..*.*(..))" id="cutPoint"/>
<aop:advisor advice-ref="selectDbAdvice" pointcut-ref="cutPoint"/>
</aop:config>
</beans>
接口使用如下配置方式:
@Component
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
@Override
public int insertUserInfo(UserInfo userInfo) {
return this.getSqlSession().insert("Order.insertUserInfo", userInfo);
}
}
現(xiàn)在突然想增加一個(gè)分頁(yè)的插件,修改的代碼如下:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
<property name="mapperLocations" value="classpath*:sqlmap/**/*.xml" />
<property name="plugins">
<array>
<bean class="com.test.dao.PerformanceInterceptor">
<property name="openTimeLog" value="true"/>
</bean>
<!-- 新增的 -->
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<!--使用下面的方式配置參數(shù),一行配置一個(gè) -->
<value>
dialect=mysql
</value>
</property>
</bean>
</array>
</property>
</bean>
不想修改原來(lái)的代碼,想讓兩種配置方式都能正常運(yùn)行,所以增加了一個(gè)自動(dòng)掃描mapper的配置,如下:
<!--配置sqlMap 文件路徑,進(jìn)行自動(dòng)掃描加載 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.dao.school"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
結(jié)果,導(dǎo)致了問(wèn)題一,如下:

使用版本如下:
mybatis-spring-1.2.0.jar
mybatis-3.2.2.jar
問(wèn)題:
在spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 進(jìn)行自動(dòng)掃描的時(shí)候,設(shè)置了sqlSessionFactory 的話,他會(huì)優(yōu)先于PropertyPlaceholderConfigurer執(zhí)行,從而導(dǎo)致PropertyPlaceholderConfigurer失效,這時(shí)在xml中用${jdbc.url}、${jdbc.username}、${password}等這樣之類(lèi)的表達(dá)式,將無(wú)法獲取到properties文件里的內(nèi)容。
處理方式:
將
<!-- mybatis config -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
<property name="mapperLocations" value="classpath*:sqlmap/**/*.xml" />
</bean>
<!--配置sqlMap 文件路徑,進(jìn)行自動(dòng)掃描加載 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.dao.school"/>
<property name="sqlSessionFactoryBeanName" value="sqlSession"/>
</bean>
修改為
<!-- mybatis config -->
<bean id="mybatisSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
<property name="mapperLocations" value="classpath*:sqlmap/**/*.xml" />
</bean>
<!--配置sqlMap 文件路徑,進(jìn)行自動(dòng)掃描加載 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.dao.school"/>
<property name="sqlSessionFactoryBeanName" value="mybatisSqlSessionFactory"/>
</bean>
原因:
使用sqlSessionFactoryBeanName注入,不會(huì)立即初始化sqlSessionFactory, 所以不會(huì)引發(fā)提前初始化問(wèn)題,同時(shí)還應(yīng)注意在配置org.mybatis.spring.SqlSessionFactoryBean這個(gè)Bean時(shí),id不能為sqlSessionFactory,如果為這樣的話會(huì)導(dǎo)致MapperScannerConigurer在bean定義加載時(shí),加載PropertyPlaceholderConfigurer還沒(méi)來(lái)得及替換定義中的變量
還有一種方式將mybatis-spring的版本換成1.0.0不會(huì)出現(xiàn)加載順序的問(wèn)題,但本人沒(méi)有測(cè)試。
改完之后,引出了問(wèn)題二,如下:

問(wèn)題:
SqlSessionDaoSupport在注入SqlSessionFactory 和 SqlSessionTemplate時(shí)失敗了,拋出了這個(gè)異常:
protected void checkDaoConfig() {
notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
解決方式:
寫(xiě)一個(gè)基類(lèi)繼承SqlSessionDaoSupport,然后讓繼承SqlSessionDaoSupport 的dao層都繼承BaseDao,這樣手動(dòng)注入一個(gè)SqlSessionFactory
public class BaseDao extends SqlSessionDaoSupport {
@Resource
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){
super.setSqlSessionFactory(sqlSessionFactory);
}
}
原因:
mybatis-spring-1.2.0中取消了自動(dòng)注入SqlSessionFactory 和 SqlSessionTemplate,所以導(dǎo)致不能自動(dòng)注入進(jìn)來(lái)。
1.2.0的源碼如下:
/**
* Convenient super class for MyBatis SqlSession data access objects.
* It gives you access to the template which can then be used to execute SQL methods.
* <p>
* This class needs a SqlSessionTemplate or a SqlSessionFactory.
* If both are set the SqlSessionFactory will be ignored.
* <p>
* {code Autowired} was removed from setSqlSessionTemplate and setSqlSessionFactory
* in version 1.2.0.
*
* @see #setSqlSessionFactory
* @see #setSqlSessionTemplate
* @see SqlSessionTemplate
* @version $Id$
*/
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
}
……
}
1.1.0源碼如下:
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
@Autowired(required = false)
public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
@Autowired(required = false)
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
}
……
}
現(xiàn)在有一個(gè)問(wèn)題有些困擾我,BaseDao基類(lèi)中,用@Resource注入SqlSessionFactory,但我在配置文件中配置的id=“mybatisSqlSessionFactory”,為什么可以注入進(jìn)來(lái)?希望各位大大能幫忙解答。
最終程序成功的跑起來(lái)了。本人第一次寫(xiě)博客,有問(wèn)題歡迎各位大大指正。
參考文章:
https://blog.csdn.net/huiwenjie168/article/details/51722290
https://www.cnblogs.com/hawk0035/p/3337283.html?utm_source=tuicool