背景
最近項目要上線,需要開發一個數據遷移程序。程序的主要功能就是將一個數據庫里的數據,查詢出來經過一系列處理后導入另一個數據庫。考慮到開發的方便快捷。自然想到用spring和mybatis整合一下。甚至用mybatis的自動代碼生成,可以省下大量dao層的開發。
整合的坑
之前的項目:以前也有過這種類似的程序,就把spring和mybatis整合的配置直接拿來修改下用。之前的整合配置是這樣子的:
1、考慮到數據庫url、用戶名密碼的可配置性,將這些信息放入properties文件。在spring配置文件里使用了
<context:property-placeholder location="classpath:config.properties" />
2、在spring配置文件里的mybatis和spring的整合配置是這樣
1
2
3
4
5
6
|
<bean id= "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > <property name= "dataSource" ref= "dataSource" /> </bean> <bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "basePackage" value= "com.lagou.chat.record.transfer.dao" /> </bean> |
以上配置是沒有問題的。所以就直接將配置拷貝到新項目
當前項目:將老項目的配置拷貝過來,但是新的項目要連接兩個數據庫,自然需要兩個數據源(record和im),就對老的配置做了如下修改
1、使用properties文件的配置不變
2、之前因為就一個數據源(一個sqlSessionFactory),所以沒有在MapperScannerConfigurer下配置<property name="sqlSessionFactory" ref="sqlSessionFactory"/>。因為默認使用sqlSessionFactory。但現在兩個數據源了,不指定肯定導致混亂。所以配置修改為如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<bean id= "record_sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > <property name= "dataSource" ref= "record_dataSource" /> </bean> <bean id= "config1" class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "basePackage" value= "com.xxx.util.rollback.record.dao" /> <property name= "sqlSessionFactory" ref= "record_sqlSessionFactory" /> </bean> <bean id= "im_sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > <property name= "dataSource" ref= "im_dataSource" /> </bean> <bean id= "config2" class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "basePackage" value= "com.xxx.util.rollback.im.dao" /> <property name= "sqlSessionFactory" ref= "im_sqlSessionFactory" /> </bean> |
結果就是運行新項目時,spring配置文件里的${jdbc.url},${jdbc.name}等屬性無法被properties里的指定值替換。一開始自然想不到是因為spring和mybatis整合的原因,所以一度不斷檢查spring配置文件是否有誤,properties文件是否有誤,是不是properties文件沒被引用到或者properties文件沒有被編譯到classpath目錄下等。當然,分析沒有分析出問題的原因,自然就不可能找到解決問題的辦法。只好求助于網絡。最終還是找到了答案
修正方式:將配置需改為如下,問題得到了解決:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<bean id= "record_sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > <property name= "dataSource" ref= "record_dataSource" /> </bean> <bean id= "config1" class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "basePackage" value= "com.xxx.util.rollback.record.dao" /> <property name= "sqlSessionFactoryBeanName" value= "record_sqlSessionFactory" /> </bean> <bean id= "im_sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > <property name= "dataSource" ref= "im_dataSource" /> </bean> <bean id= "config2" class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "basePackage" value= "com.xxx.util.rollback.im.dao" /> <property name= "sqlSessionFactoryBeanName" value= "im_sqlSessionFactory" /> </bean> |
就是將sqlSessionFactory屬性改為sqlSessionFactoryBeanName。當然也得將ref改為value。因為sqlSessionFactoryBeanName屬性是字符串類型
原因
spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 進行自動掃描的時候,設置了sqlSessionFactory 的話,可能會導致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}這樣之類的表達式,將無法獲取到properties文件里的內容。
導致這一原因是因為,MapperScannerConigurer實際是在解析加載bean定義階段的,這個時候要是設置sqlSessionFactory的話,會導致提前初始化一些類,這個時候,PropertyPlaceholderConfigurer還沒來得及替換定義中的變量,導致把表達式當作字符串復制了。 但如果不設置sqlSessionFactory 屬性的話,就必須要保證sessionFactory在spring中名稱一定要是sqlSessionFactory ,否則就無法自動注入。
以上所述是小編給大家介紹的Spring整合Mybatis使用<context:property-placeholder>時的坑 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!