Springboot整合mybatis实现多数据源所遇到的问题

项目场景:

在项目中需要从多个数据库中取数据时就需要配置多个数据源,我们可以通过jdbcTemplate来完成,但是需要将查询的sql显示在代码中,为了实现对以往代码结构不产生影响,所以使用了Springboot整合mybatis实现多数据源。


问题描述:

配置好以后我出现的第一个问题就是在启动的时候报错,说找不到mapper1路径下的xml文件,因为没有创建。然后我看项目中真的有啊。报错信息如下:

1
2
3
4
5
6
7
8
9
10
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/rmp/config/DatabaseConfig.class]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'class path resource [classpath*:/mapper/mapper1/*.xml]'; nested exception is java.io.FileNotFoundException: class path resource [classpath*:/mapper/mapper1/*.xml] cannot be opened because it does not exist
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:860) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]

原因分析:

然而我的项目中明明有这个路径和xml文件,根据错误找到配置mapper文件路径的地方。重点在给设置SqlSessionFactory配置mapper路径那里。

1
2
3
4
5
6
7
8
9
10
/** 创建SessionFactory */
    @Primary
    @Bean(name = "ds1SqlSessionFactory")
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {<!-- -->
        SqlSessionFactory bean = new SqlSessionFactory ();
        bean.setDataSource(dataSource);
        //设置mapper路径
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResource(classpath*:mapper/mapper1/*.xml));
        return bean.getObject();
    }

解决方案:

为SqlSessionFactory设置mapper路径时将getResources()写成了getResource()。少写了一个s。所以以此总结出能复制还是不要自己敲了的真理。

1
2
3
4
//获取所有类路径下的指定文件
getResources()
//表示从当前类的根路径去查找资源,能获取到同一个包下的文件
getResource()

问题二:

从数据库查询到的值create_time获取不到值,其余数据均可以拿到值,刚开始以为是日期类型的问题,后来发现是配置多数据源之后之前在properties路径下的mybatis配置的数据库与实体类的驼峰映射失效:

解决方案:

在设置多数据源的配置文件中的SqlSessionFactory中添加如下配置

1
2
3
4
5
6
7
8
9
10
    @Primary
    @Bean(name = "ds1SqlSessionFactory")
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {<!-- -->
        SqlSessionFactory bean = new SqlSessionFactory ();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        //设置驼峰映射
        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
       return bean.getObject();
    }

问题三:

之前使用到的mybatis-plus中mapper中的通用方法都失效了,查找不到baseMapper中的方法,仅自己写的方法有效,报错如下:

1
2
3
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.rmp.mapper.mapper1.TaskPlanMapper.selectPage
    at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.5.jar:3.5.5]
    at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) ~[mybatis-3.5.5.jar:3.5.5]

解决方法:

由于使用的mybatis中的原生SqlSessionFactory,所以Mybatis-plus中的方法都没有被加载,仅需将SqlSessionFactory替换成MybatisSqlSessionFactoryBean即可成功使用

1
2
3
4
5
6
7
8
9
10
    @Primary
    @Bean(name = "ds1SqlSessionFactory")
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {<!-- -->
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        //设置驼峰映射
        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return bean.getObject();
    }

问题四:

使用mybatis-plus的分页插件发现获取结果集有数据,但是总条数的getTotal()方法始终为0

解决办法

1
2
3
4
5
6
7
    /**  配置分页插件 */
    @Bean
    public PaginationInterceptor paginationInterceptor() {<!-- -->
        PaginationInterceptor page = new PaginationInterceptor();
        page.setDialectType("mysql");
        return page;
    }