Springboot 配置多数据源Mybatis的MapUnderScoreToCamelCase不生效

2018/04/28 08:10
阅读数 195

摘要

本文是一篇问题解决经验分享的文章。因为在网上没有搜到相关的介绍文章,而在遇到这个问题的解决过程中,犯过一些想当然的错误,所以记录在此,希望能够对后面遇到此问题的朋友有所帮助

问题

参考官方文档进行了相关配置。

https://github.com/mybatis/spring-boot-starter/blob/master/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.java

  1. 通过MybatisProperties 将application.yml文件中mybatis相关配置映射到properties文件中

  2. 通过MybatisAutoConfiguration注入SqlSessionFactory的Bean到容器中

通过这个配置,就可以在代码中开心的通过mybatis的操作数据库了。

但是这种方式只能配置一种数据源,像下面这样再配置一个

  
    
  
  
  1.  @Bean(name = "siteASqlSessionFactory")

  2.  @ConditionalOnMissingBean

  3.  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

  4.    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();

  5.    factory.setDataSource(dataSource);

  6.    factory.setVfs(SpringBootVFS.class);

  7.    if (StringUtils.hasText(this.properties.getConfigLocation())) {

  8.      factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));

  9.    }

  10.    applyConfiguration(factory);

  11.    if (this.properties.getConfigurationProperties() != null) {

  12.      factory.setConfigurationProperties(this.properties.getConfigurationProperties());

  13.    }

  14.    if (!ObjectUtils.isEmpty(this.interceptors)) {

  15.      factory.setPlugins(this.interceptors);

  16.    }

  17.    if (this.databaseIdProvider != null) {

  18.      factory.setDatabaseIdProvider(this.databaseIdProvider);

  19.    }

  20.    if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {

  21.      factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());

  22.    }

  23.    if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {

  24.      factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());

  25.    }

  26.    if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {

  27.      factory.setMapperLocations(this.properties.resolveMapperLocations());

  28.    }

  29.    return factory.getObject();

  30.  }

问题1:如果再配置一个,像上面那样,会发现报错,找不到对应的表schema,sql执行失败。

SprintBootVFS com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'site.post' doesn't exist at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4098) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4030) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2671) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2621) at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557) at com.alibaba.druid.pool.DruidPooledStatement.executeQuery(DruidPooledStatement.java:140) at com.taobao.tddl.atom.jdbc.TStatementWrapper.executeQuery(TStatementWrapper.java:260) at com.taobao.tddl.group.jdbc.TGroupStatement.executeQueryOnConnection(TGroupStatement.java:426) at com.taobao.tddl.group.jdbc.TGroupStatement$3.tryOnDataSource(TGroupStatement.java:439) at com.taobao.tddl.group.jdbc.TGroupStatement$3.tryOnDataSource(TGroupStatement.java:430) at

然后就改成下面这样,另外一个数据源改成这样的配置

  
    
  
  
  1. @Bean(name = "siteASqlSessionFactory")

  2.    public SqlSessionFactory siteASqlSessionFactory(@Qualifier("siteADataSource") DataSource siteATaskDataSource)

  3.            throws Exception {

  4.        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

  5.        sessionFactory.setDataSource(siteATaskDataSource);

  6.        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()

  7.                .getResources(SiteADataSourceConfig.MAPPER_LOCATION));

  8.        return sessionFactory.getObject();

  9.    }

问题2:问题就遇到了,如题所说,mapUnderScoreToCamelCase配置不生效,一开始没理解为什么不生效,明明application.yml中已经配置了。但是分析了一下就知道,因为mapUnderScoreToCamelCase是Configuration的一个属性,之前习惯了这种配置,框架帮忙做了,不了解其原理,在这边SqlSessionFactory中根本没有配置configuration对象,当然不生效。

所以现在了解了问题,mapUnderScoreToCamelCase是Configuration的一个属性,Configuration需要注入到SqlSesssionFactory中。然后配置多个数据源后,为什么会找不到第二个数据源的schema了。通过debug发现,

Configuration类中有一个变量Environment,

  
    
  
  
  1. protected Environment environment;

Environment中有个DataSource对象,这个之前我们介绍过,是数据库连接对象,所以问题比较清楚了,当注入第一个sqlSessionFactory后数据库连接时正常的,但是当注入第二个数据源的sqlSessionFactory,由于Configuration.Environment.DataSource已经配置了第一个数据源的信息,所以在web容器启动后,进行数据库操作时,会报找不到数据库schema

  
    
  
  
  1. public final class Environment {

  2.  private final String id;

  3.  private final TransactionFactory transactionFactory;

  4.  private final DataSource dataSource;

  5.  }

解决

找到root cause后,解决就简单了。配置两个Configuration就好了 数据源1

  
    
  
  
  1.  @Bean(name = "siteASqlSessionFactory")

  2.    public SqlSessionFactory siteASqlSessionFactory(@Qualifier("siteADataSource") DataSource siteADataSource)

  3.            throws Exception {

  4.        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

  5.        sessionFactory.setDataSource(siteADataSource);

  6.        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()

  7.                .getResources(siteADataSourceConfig.MAPPER_LOCATION));

  8.        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session

  9.                .Configuration();

  10.        configuration.setMapUnderscoreToCamelCase(true);

  11.        sessionFactory.setConfiguration(configuration);

  12.        return sessionFactory.getObject();

  13.    }

数据源2

  
    
  
  
  1. ```

  2.  @Bean(name = "siteBSqlSessionFactory")

  3.    public SqlSessionFactory siteASqlSessionFactory(@Qualifier("siteBDataSource") DataSource siteADataSource)

  4.            throws Exception {

  5.        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

  6.        sessionFactory.setDataSource(siteBDataSource);

  7.        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()

  8.                .getResources(siteBDataSourceConfig.MAPPER_LOCATION));

  9.        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session

  10.                .Configuration();

  11.        configuration.setMapUnderscoreToCamelCase(true);

  12.        sessionFactory.setConfiguration(configuration);

  13.        return sessionFactory.getObject();

  14.    }

扫面二维码,了解更多


本文分享自微信公众号 - 方丈的寺院(gh_c98f244e174d)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部