背景
最近项目要上线,需要开发一个数据迁移程序。程序的主要功能就是将一个数据库里的数据,查询出来经过一系列处理后导入另一个数据库。考虑到开发的方便快捷。自然想到用spring和mybatis整合一下。甚至用mybatis的自动代码生成,可以省下大量dao层的开发。
整合的坑
之前的项目:以前也有过这种类似的程序,就把spring和mybatis整合的配置直接拿来修改下用。之前的整合配置是这样子的:
1、考虑到数据库url、用户名密码的可配置性,将这些信息放入properties文件。在spring配置文件里使用了
<context:property-placeholder location=\"classpath:config.properties\" />
2、在spring配置文件里的mybatis和spring的整合配置是这样
<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。但现在两个数据源了,不指定肯定导致混乱。所以配置修改为如下
<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目录下等。当然,分析没有分析出问题的原因,自然就不可能找到解决问题的办法。只好求助于网络。最终还是找到了答案
修正方式:将配置需改为如下,问题得到了解决:
<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>时的坑 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对phpstudy网站的支持!
本文地址:https://www.stayed.cn/item/6470
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我