首页 > 技术文章 > springboot mybatis使注解和xml两种方式同时生效

gunduzi 2019-11-18 09:46 原文

声明:该博客参考了:https://www.jianshu.com/p/53762ac6d31c

如果上面这个博客中的内容已经解决了你的问题,那就不用往下看了,如何按照上面的配置一直报这个异常:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

请参考如下博客解决:https://blog.csdn.net/softwarehe/article/details/8889206

如果仍然无法解决,可以尝试下面的方法,这也是我写这篇博客的目的。

一般在项目中都会使用springboot,如果需要使用mysql,一般都会使用阿里的druid数据库连接池,那使用这个连接池的时候,一般都会对druid做一些配置,有的人喜欢在yml中直接配置了,但是有些人可能在程序中搞一个配置类:类似于下面这种(没有全部贴出来,太长):

@Configuration
@MapperScan(basePackages = "com.gbgg.graph.goods.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class DuridConfig {
	@Value("${spring.datasource.primary.url:#{null}}")
	private String dbUrl;
	@Value("${spring.datasource.primary.username: #{null}}")
	private String username;
	@Value("${spring.datasource.primary.password:#{null}}")
	private String password;
	@Value("${spring.datasource.primary.driverClassName:#{null}}")
	private String driverClassName;
	@Value("${spring.datasource.initialSize:#{null}}")
	private Integer initialSize;
	@Value("${spring.datasource.minIdle:#{null}}")
	private Integer minIdle;
	@Value("${spring.datasource.maxActive:#{null}}")
	private Integer maxActive;
	@Value("${spring.datasource.maxWait:#{null}}")
	private Integer maxWait;
	@Value("${spring.datasource.timeBetweenEvictionRunsMillis:#{null}}")
	private Integer timeBetweenEvictionRunsMillis;
	@Value("${spring.datasource.minEvictableIdleTimeMillis:#{null}}")
	private Integer minEvictableIdleTimeMillis;
	@Value("${spring.datasource.validationQuery:#{null}}")
	private String validationQuery;
@Bean(name = "jdbcTemplate")@Primary
public JdbcTemplate jdbcTemplate() {
   return new JdbcTemplate(dataSource());
}

@Bean(name = "transactionManager")
@Primary
public DataSourceTransactionManager transactionManager() {
   return new DataSourceTransactionManager(dataSource());
}

@Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory setSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

这个配置类中自己new了一个SqlSessionFactoryBean,这就会导致在yml文件中配置的xml路径根本不起作用,也就是说根本找不到xml文件,所以上面的异常就会一直报。那怎么解决呢?

就是在在即new 的这个SqlSessionFactoryBean中,把xml路径给指定了就可以了,那怎么指定呢,看下面代码:

@Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory setSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
		configuration.setCallSettersOnNulls(true);
		bean.setConfiguration(configuration);
		bean.setVfs(SpringBootVFS.class);
        //下面这两个就是指定xml路径的
		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		bean.setMapperLocations(resolver.getResources("classpath*:/mapper/*.xml"));
                bean.setDataSource(dataSource);
        return bean.getObject();
    }

 好了,以上就是这个问题的解决办法,但有个问题,为什么这里自己new了一个SqlSessionFactoryBean之后,yml文件中配置的就不起作用了呢?这个还在研究,等以后更新,如果有那位大佬知道原理,也麻烦在评论中告知。

------------------------------------------------2019-11-19更新--------------------------------------------------------------

上面的代码在idea中执行时ok的,但是打完包,发到服务器上运行会一直报如下错误:

Mapped Statements collection already contains value for

网上的解释大约有如下几种原因:

  1. xml中的id有重复的
  2. mapper接口文件中出现了接口重载
  3. xml中有些方法的返回值类型没有指定

以上这些基本都很容易检查出来,在idea中就会抛出该异常,但是在idea中没有抛出该异常,那就说明程序的语法,逻辑应该没问题,那就应该是打完包之后文件路径变更导致的,我这个就是这种情况,如果是classpath*:/mapper/*.xml这种写法,在服务器上会当成一个绝对路径进行寻找,但是实际上这个mapper文件是在resources下放着,打包之后的文件目录如下:

 正确的写法应该是:classpath:mapper/*.xml,但是这里仍然有个问题,为什么在idea中没有抛出这个异常?

 

推荐阅读