主要针对 Mapper 3.x 版本,升级到 4.x 能解决常见的 mappers 参数问题
常见症状:
Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL)
java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.SpecialProvider.()
出现这个问题的原因是因为你用到了 tk.mybatis.mapper.common.Mapper
之外的其他接口,例如:
MySqlMapper
SqlServerMapper
InsertListMapper
InsertUseGeneratedKeysMapper
当你没有配置 mappers
参数的时候,通用 Mapper 只会解析 tk.mybatis.mapper.common.Mapper
中提供的方法,所以你使用不包含在内的其他方法时就会报错。
通常在使用接口时,都会创建自己的 BaseMapper
接口,例如:
package x.y.z;
//import ...
public interface BaseMapper extends Mapper, MySqlMapper {
}
这种情况下,如果你不正确配置 mappers
参数,你就无法使用 MySqlMapper
中提供的几个方法。
配置方法如下
在使用 Spring XML 方式配置时,配置如下:
mappers=x.y.z.BaseMapper
想要配置其他属性时,一行配置一个 key=value 即可。
在 Spring Boot 中,可以直接在配置文件中按照下面方式指定:
mapper.mappers=x.y.z.BaseMapper
在1.集成通用 Mapper 文档中有很多种集成方式,文档中详细介绍了如何进行配置。
由于 Devtools 使用不同的类加载器实现的动态加载,经过测试发现 Spring Boot 使用 Devtools 的时候,@RegisterMapper
等类会使用 RestarClassLoader
进行加载,而 AppClassLoader
会加载不需要重启的类, 而前者的 parent 是后者,这就导致 AppClassLoader
加载的 XXMapper
,在初始化时,由于获取不到另一个类加载器加载的注解类,导致获取失败,因而导致了初始化失败,后续方法都无法调用(包括Example创建)。
目前的解决版本就是先禁用 Devtools,后续更新会尝试解决该问题。
该问题影响的版本为:4.0.0~4.0.2。
常见异常:
出现这个问题的原因有两种。
第一种情况通常是通用 Mapper 没有配置好,没有对 MyBatis 方法初始化造成的。常见的判断方法就是看看其他非 Example
的通用方法能否执行,如果不能执行就是配置的问题。如果能正常执行,可能就是第二种情况。
第二种情况就是调用方法的位置或者时机早于通用 Mapper 初始化,这种情况下可以通过升级到 4.x 版本解决,4.x 版本的所有配置方式理论上都是在 MyBatis 初始化的同时进行的,也就是在你能使用 MyBatis 的时候,通用 Mapper 就已经准备好了。如果还存在这种问题,就可以使用 XML 配置方式中的 Configuration
方式,参考这里XML 配置使用 Configuration。Spring Boot 参考下面的代码:
https://github.com/abel533/Mapper/blob/819ad48389d1766a6a8304aae282a58be9132708/spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java#L191-L197
如果你使用了 @tk.xxx.MapperScan
注解(包名必填),通用 Mapper 就会自动处理所有通用方法。
如果不使用该注解,你没有别的办法设置包名,所以通用 Mapper 就无法判断哪些接口属于 DAO 层,因此你需要给所有的 Mapper 接口增加 @org.xxx.Mapper
注解,否则 MyBatis 就扫描不到任何接口。
通过查找依赖发现 activiti 中存在下面的依赖:
org.hibernate.javax.persistence
hibernate-jpa-2.1-api
x.x.x
这个依赖和 Mapper 中的 JPA 依赖有冲突:
javax.persistence
persistence-api
x.x.x
按照类加载顺序,persistence-api-1.0.jar 会更早的加载,因此会出错。
解决办法就是排除 Mapper 自带的这个依赖,使用 hibernate 这个 JPA 就能解决。
排除方式如下:
tk.mybatis
mapper
x.x.x
persistence-api
javax.persistence