• 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));
      }
    }
    
  • 相关阅读:
    (转+原)android获取系统时间
    (转+原)VC编译错误:uafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMT.lib(new.obj) 中定义
    android的reference table的问题
    (原+转)Eclipse中Android调用OpenCv
    JAVA IO 字符流 FileReader FileWriter
    JAVA IO
    JAVA FIle类
    JAVA 泛型
    JAVA Collection工具类 Collections
    JAVA Map子接口之 HashMap
  • 原文地址:https://www.cnblogs.com/nuccch/p/9063719.html
Copyright © 2020-2023  润新知