Spring 集成 MyBatis: 自动注入映射器导致项目启动报错

需求描述:

在公司使用Spring(3.2.12.RELEASE) + MyBatis(3.2.7) + MyBatis-Spring(1.2.2) 集成。在之前的项目中,接口是不需要再写实现类的,但是现在做的项目使用之前的技术架构需要写dao的实现类,我觉得这样特别的麻烦。原因:1. dao层不处理业务逻辑,只负责持久化,在业务层保证数据准确的前提下,dao不需要再对数据进行验证。2. MyBatis 官方也提供了相应的注入映射器的方案。所以我认为,应该按照官方的方案去做。

问题描述:

使用官方的方案与Spring集成后,项目启动便报错。

1. 错误信息如下:

严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0' defined in class path resource [bean/dao-env-bean.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [bean/dao-env-bean.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [bean/dao-env-bean.xml]: Cannot resolve reference to bean 'writeDataSource' while setting bean property 'targetDataSources' with key [TypedStringValue: value [master], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'writeDataSource' defined in class path resource [bean/dao-env-bean.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name ${dataSource.jndi.master} is not bound in this Context
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:441)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:626)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
	at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [bean/dao-env-bean.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [bean/dao-env-bean.xml]: Cannot resolve reference to bean 'writeDataSource' while setting bean property 'targetDataSources' with key [TypedStringValue: value [master], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'writeDataSource' defined in class path resource [bean/dao-env-bean.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name ${dataSource.jndi.master} is not bound in this Context
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1419)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1160)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1178)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1128)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
	... 24 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [bean/dao-env-bean.xml]: Cannot resolve reference to bean 'writeDataSource' while setting bean property 'targetDataSources' with key [TypedStringValue: value [master], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'writeDataSource' defined in class path resource [bean/dao-env-bean.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name ${dataSource.jndi.master} is not bound in this Context
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:384)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:165)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1419)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1160)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
	... 36 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'writeDataSource' defined in class path resource [bean/dao-env-bean.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name ${dataSource.jndi.master} is not bound in this Context
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1514)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
	... 48 more
Caused by: javax.naming.NameNotFoundException: Name ${dataSource.jndi.master} is not bound in this Context
	at org.apache.naming.NamingContext.lookup(NamingContext.java:820)
	at org.apache.naming.NamingContext.lookup(NamingContext.java:168)
	at org.apache.naming.SelectorContext.lookup(SelectorContext.java:158)
	at javax.naming.InitialContext.lookup(InitialContext.java:417)
	at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
	at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
	at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
	at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
	at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
	at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
	at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:231)
	at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:217)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1573)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)
	... 55 more

2. 配置信息如下:

<!-- mybatis config -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	  <property name="dataSource" ref="dataSource" />
	  <property name="configLocation" value="classpath:mybatis/mysql-sqlmap.xml" />
	  <property name="mapperLocations" value="classpath:mybatis/sqlmap/*.xml" />
	</bean>
	
	<!-- 注册映射器,dao接口 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.******.dao" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	</bean>

解决方案:

查询后,网上说因为使用MapperScannerConfigurer的扫描模式导bean的加载顺序改变而使得PropertyPlaceholderConfigurer无法正常加载。只要修改下配置即可解决:

<!-- mybatis config -->
	<bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	  <property name="dataSource" ref="dataSource" />
	  <property name="configLocation" value="classpath:mybatis/mysql-sqlmap.xml" />
	  <property name="mapperLocations" value="classpath:mybatis/sqlmap/*.xml" />
	</bean>
	
	<!-- 注册映射器,dao接口 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.********.dao" />
		<property name="sqlSessionFactoryBeanName" value="mySqlSessionFactory"></property>
	</bean>

与之前配置的差异性:SqlSessionFactoryBean的实例化名称变成了自定义名称mySqlSessionFactory而不是sqlSessionFactory

修改配置后,项目正常启动。


参考链接:

1. http://yjy110.iteye.com/blog/1882876

2. http://www.mybatis.org/spring/zh/mappers.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值