zoukankan      html  css  js  c++  java
  • MyBatis集成到Spring时配置MapperScannerConfigurer出错

    问题描述

    在web项目中同时集成了spring mvc和mybatis。
    将jdbc配置参数独立在外部配置文件中,然后通过<context:property-placeholder>引入。
    此时在Spring中注入org.mybatis.spring.mapper.MapperScannerConfigurer,如下所示:

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.chench.test.springmvc.dao" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    

    如果直接配置属性sqlSessionFactory,并设置为指定的sqlSessionFactory对象,那么在启动spring时会报错:

    Caused by: java.lang.NumberFormatException: For input string: "${master.acquireIncrement}"
    

    数据源配置中无法正确引用外部文件中配置的jdbc参数。

    必须修改为配置属性sqlSessionFactoryBeanName,才能正确引用到对应的jdbc配置参数。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.chench.test.springmvc.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
    

    这是什么原因呢?

    原因分析及解决方案

    实际上,这是MyBatis早期版本的一个BUG,详见:https://github.com/mybatis/old-google-code-issues/issues/414
    而且,在最新版本的MyBatis中,同样不再推荐使用设置Bean属性的方式,而是通过设置Value属性。

      /**
       * Specifies which {@code SqlSessionFactory} to use in the case that there is
       * more than one in the spring context. Usually this is only needed when you
       * have more than one datasource.
       * <p>
       * @deprecated Use {@link #setSqlSessionFactoryBeanName(String)} instead.
       *
       * @param sqlSessionFactory
       */
       // 这是一个声明为废弃的方法,不推荐使用
      @Deprecated
      public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
      }
      
      /**
       * Specifies which {@code SqlSessionFactory} to use in the case that there is
       * more than one in the spring context. Usually this is only needed when you
       * have more than one datasource.
       * <p>
       * Note bean names are used, not bean references. This is because the scanner
       * loads early during the start process and it is too early to build mybatis
       * object instances.
       *
       * @since 1.1.0
       *
       * @param sqlSessionFactoryName Bean name of the {@code SqlSessionFactory}
       */
      // 解释了为什么应该使用设置Value的方式而不是引用Bean的原因
      public void setSqlSessionFactoryBeanName(String sqlSessionFactoryName) {
        this.sqlSessionFactoryBeanName = sqlSessionFactoryName;
      }
    

    实际上,通常情况下无需手动为MapperScannerConfigurer注册SqlSessionFactory,这个工作由Spring框架完成,因为MapperScannerConfigurer已经实现了接口BeanDefinitionRegistryPostProcessor。

    public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
    	@Override
      public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        if (this.processPropertyPlaceHolders) {
          processPropertyPlaceHolders();
        }
    
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setAddToConfig(this.addToConfig);
        scanner.setAnnotationClass(this.annotationClass);
        scanner.setMarkerInterface(this.markerInterface);
        // 由Spring框架自动注入SqlSessionFactory
        scanner.setSqlSessionFactory(this.sqlSessionFactory);
        scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
        // 由Spring框架自注入sqlSessionFactoryBeanName
        scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
        scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
        scanner.setResourceLoader(this.applicationContext);
        scanner.setBeanNameGenerator(this.nameGenerator);
        scanner.registerFilters();
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
      }
    }
    
  • 相关阅读:
    一月5日
    一月5日
    面试java工程师的自我介绍(模拟篇)
    Spring Boot Jpa 介绍
    spring+redis做缓存使用
    Spring Boot Web 开发详解
    thymeleaf+spring的简单搭建
    如何搭建 Spring boot
    通用baseDao
    pagehelper的使用
  • 原文地址:https://www.cnblogs.com/nuccch/p/9063719.html
Copyright © 2011-2022 走看看