七、常见问题

1. mappers 参数导致的各种错误

主要针对 Mapper 3.x 版本,升级到 4.x 能解决常见的 mappers 参数问题

常见症状:

  • Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL)
  • java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.SpecialProvider.<init>()

出现这个问题的原因是因为你用到了 tk.mybatis.mapper.common.Mapper<T> 之外的其他接口,例如:

  • MySqlMapper
  • SqlServerMapper
  • InsertListMapper
  • InsertUseGeneratedKeysMapper

当你没有配置 mappers 参数的时候,通用 Mapper 只会解析 tk.mybatis.mapper.common.Mapper<T> 中提供的方法,所以你使用不包含在内的其他方法时就会报错。

通常在使用接口时,都会创建自己的 BaseMapper<T> 接口,例如:

  1. package x.y.z;
  2. //import ...
  3. public interface BaseMapper<T> extends Mapper<T>, MySqlMapper<T> {
  4. }

这种情况下,如果你不正确配置 mappers 参数,你就无法使用 MySqlMapper<T> 中提供的几个方法。

配置方法如下

在使用 Spring XML 方式配置时,配置如下:

  1. <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
  2. <property name="basePackage" value="tk.mybatis.mapper.xml"/>
  3. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  4. <property name="properties">
  5. <value>
  6. mappers=x.y.z.BaseMapper
  7. </value>
  8. </property>
  9. </bean>

想要配置其他属性时,一行配置一个 key=value 即可。

在 Spring Boot 中,可以直接在配置文件中按照下面方式指定:

  1. mapper.mappers=x.y.z.BaseMapper

1.集成通用 Mapper 文档中有很多种集成方式,文档中详细介绍了如何进行配置。

1.1 使用 Devtools 时也会引发上面的问题

由于 Devtools 使用不同的类加载器实现的动态加载,经过测试发现 Spring Boot 使用 Devtools 的时候,@RegisterMapper 等类会使用 RestarClassLoader 进行加载,而 AppClassLoader 会加载不需要重启的类,
而前者的 parent 是后者,这就导致 AppClassLoader 加载的 XXMapper ,在初始化时,由于获取不到另一个类加载器加载的注解类,导致获取失败,因而导致了初始化失败,后续方法都无法调用(包括Example创建)。

目前的解决版本就是先禁用 Devtools,后续更新会尝试解决该问题。

该问题影响的版本为:4.0.0~4.0.2。

2. Example 无法获取实体类xxx.Yyy对应的表名!

常见异常:

  • java.lang.RuntimeException: 无法获取实体类xxx.Yyy对应的表名!`

出现这个问题的原因有两种。

第一种情况通常是通用 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

3. Spring Boot 中注解注意事项

如果你使用了 @tk.xxx.MapperScan 注解(包名必填),通用 Mapper 就会自动处理所有通用方法。

如果不使用该注解,你没有别的办法设置包名,所以通用 Mapper 就无法判断哪些接口属于 DAO 层,因此你需要给所有的 Mapper 接口增加 @org.xxx.Mapper 注解,否则 MyBatis 就扫描不到任何接口。

4. 集成 Activiti BPM 出错

通过查找依赖发现 activiti 中存在下面的依赖:

  1. <dependency>
  2. <groupId>org.hibernate.javax.persistence</groupId>
  3. <artifactId>hibernate-jpa-2.1-api</artifactId>
  4. <version>x.x.x</version>
  5. </dependency>

这个依赖和 Mapper 中的 JPA 依赖有冲突:

  1. <dependency>
  2. <groupId>javax.persistence</groupId>
  3. <artifactId>persistence-api</artifactId>
  4. <version>x.x.x</version>
  5. </dependency>

按照类加载顺序,persistence-api-1.0.jar 会更早的加载,因此会出错。

解决办法就是排除 Mapper 自带的这个依赖,使用 hibernate 这个 JPA 就能解决。

排除方式如下:

  1. <dependency>
  2. <groupId>tk.mybatis</groupId>
  3. <artifactId>mapper</artifactId>
  4. <version>x.x.x</version>
  5. <exclusions>
  6. <exclusion>
  7. <artifactId>persistence-api</artifactId>
  8. <groupId>javax.persistence</groupId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>

5. mysql的驱动版本导致的mapper-generator生成实体类的@Id问题

参考:https://github.com/abel533/Mapper/issues/463