常见问题
本文档收录了 MyBatis-Plus 使用时遇到的各种常见问题,如果您在使用 MyBatis-Plus 的时候遇到了问题,请您优先查看本文档。
以下三种方式选择一种即可:
- Spring MVC 配置(参考 mybatisplus-spring-mvc )
- Spring Boot 配置(参考 mybatisplus-spring-boot )
- 将配置文件放在 resource 文件夹中
- 对于 Maven 项目,可指定 POM 文件的 resource
- 修改类型tinyint(1)为tinyint(2)或者int
-
需要修改请求连接添加参数
tinyInt1isBit=false
,如下: - 使用自定义的 Map 对象或者普通的 Java 对象来传递参数。
- 通过在方法参数中使用 @Param(“page”) int page, @Param(“size”) int size 来传递页码和每页大小。
- SQL 长度存在限制:处理海量数据时,单条 SQL 可能无法执行或者容易引起内存泄漏、JDBC 连接超时等问题。
- 不同数据库的单条 SQL 批量语法不一致,不利于通用性。
- 解决方案:采用循环预处理批量提交的方法。虽然性能比单条 SQL 插入稍慢,但可以解决上述问题。
- 将 Druid 数据源升级至 1.1.21 版本以上,以解决此问题。
- 如果无法升级 Druid 数据源,可以选择保持 MyBatis Plus 版本在 3.1.0 及之前的版本。
- 若要继续使用最新的 MyBatis Plus 版本,可以考虑更换其他兼容新版 JDBC 的数据源,以避免出现此异常。
- 升级您的 JDBC 驱动至支持 JDBC 4.2 API 的版本。
- 如果无法升级 JDBC 驱动,可以考虑将 MyBatis Plus 版本回滚至 3.1.0 或之前的版本。
- 将 Spring Boot 降级至 2.1.x 版本,或升级至 2.2.1 版本以上。建议直接升级至 Spring Boot 2.2.2 版本以获取更好的稳定性和修复。
-
去除
spring-boot-maven-plugin
插件进行打包,或者 - 升级至 MyBatis Plus 3.3.2 版本。您可以参考示例 分离打包 进行操作。
-
如果您使用了
@TableField
注解,并希望保持全局格式化,需要设置参数keepGlobalFormat=true
。 -
您也可以在
@TableField
注解中直接指定固定格式的数据库关键词,例如@TableField("'status'")
。 -
使用变量
_databaseId
: -
使用标签属性
databaseId
: - 查看本机hostname
- 编辑系统hosts文件,将本机hostname写入至hosts文件
- 原因:驱动配置不兼容
使用
transient
修饰
使用
static
修饰
使用
TableField
注解
使用
transient
修饰需要排除的父类属性
出现该异常通常是由于配置不正确或者 Mapper 没有被正确扫描到导致的。解决方案如下:
检查是否存在 jar 包冲突。
检查 Mapper.java 的扫描路径:
方法一:在
Configuration
类上使用注解
MapperScan
方法二:在
Configuration
类中配置
MapperScannerConfigurer
(
查看示例
)
检查是否指定了主键。如果未指定,将导致
selectById
相关 ID 无法操作。请使用注解
@TableId
注解表 ID 主键。当然,
@TableId
注解可以省略,但是你的主键必须叫 id(忽略大小写)。
不要使用原生的 SqlSessionFactory,请使用 MybatisSqlSessionFactory。
检查是否自定义了 SqlInjector,是否复写了
getMethodList()
方法。在该方法中是否注入了你需要的方法(可参考 DefaultSqlInjector)。
IDEA 默认的 build 步骤可能会导致 mapper 文件无法正常编译到对应的 resources 文件夹中。请检查 build 后相关资源文件夹是否有对应的 XML 文件。如果没有,请调整 IDEA 的 build 设置。推荐调整为 Maven 或 Gradle 的 build。
问题描述:指在 XML 中里面自定义 SQL,却无法调用。本功能同
MyBatis
一样需要配置 XML 扫描路径:
对于
IDEA
系列编辑器,XML 文件是不能放在 java 文件夹中的,IDEA 默认不会编译源码文件夹中的 XML 文件,可以参照以下方式解决:
MapperScan 需要排除 com.baomidou.mybatisplus.mapper.BaseMapper 类 及其 子类(自定义公共 Mapper),比如:
原因:低版本不支持泛型注入,请升级 Spring 版本到 4+ 以上。
版本引入问题:3.4.1 版本里没有,3.4.2 里面才有!
检查是不是用了
long
而不是
Long
!
JavaScript 无法处理 Java 的长整型 Long 导致精度丢失,具体表现为主键最后两位永远为 0,解决思路: Long 转为 String 返回
FastJson 处理方式
JackJson 处理方式
方式二:调整字段验证注解
根据具体情况,在需要更新的字段中调整验证注解,如验证非空:
方式三:使用
UpdateWrapper
(3.x)
使用以下方法来进行更新或插入操作:
默认mysql驱动会把tinyint(1)字段映射为boolean: 0=false, 非0=true
MyBatis 是不会自动处理该映射,如果不想把tinyint(1)映射为boolean类型:
原因:配了 2 个分页拦截器! 检查配置文件或者代码,只留一个!
insert 后主键会自动 set 到实体的 ID 字段,所以你只需要 getId() 就好
EntityWrapper.sqlSelect 配置你想要查询的字段
我们建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现。
如果你按照 mybatis 的方式配置第三方二级缓存,并且使用 2.0.9 以上的版本,则会发现自带的方法无法更新缓存内容,那么请按如下方式解决(二选一):
1.在代码中 mybatis 的 mapper 层添加缓存注释,声明 implementation 或 eviction 的值为 cache 接口的实现类
2.在对应的 mapper.xml 中将原有注释修改为链接式声明,以保证 xml 文件里的缓存能够正常
配置 jdbcTypeForNull=NULL Spring Bean 配置方式:
yml 配置
在自定义 SQL 中,由于 Page 对象继承自 RowBounds,在 Mapper 中无法直接获取。为了解决这个问题,请考虑以下替代方案:
这些方法可以帮助您在自定义 SQL 中正确传递参数,确保代码的顺利运行。
当使用
resultType="java.util.Map"
时,您可以通过以下步骤在 Spring Boot 中实现下划线自动转换为驼峰:
在您的 Spring Boot 项目中创建一个配置类。
通过这样配置,您就可以实现自动将 Map 中的下划线转换为驼峰形式。这样,在 MyBatis 查询结果映射到 Map 对象时,键名会自动进行转换,使得您在代码中更加便捷地访问数据。
您可以通过以下方式在 Wrapper 中使用
limit
限制 SQL 结果集:
这段代码会在 SQL 语句末尾添加 limit 1,以限制结果集返回的行数为 1。
将通用的批量插入操作放在 Service 层处理有以下原因:
如果您想使用单条 SQL 插入方案,可以自行注入选装方法 insertbatchsomecolumn ,或查看 SQL 注入器 中提供的方法。
在 MyBatis Plus 3.x 中,不再提供自动识别关键字进行处理的功能。处理数据库关键字的方法有以下几种:
不同数据库对关键字的处理方式不同,因此很难维护。在数据库设计时,建议避免使用关键字作为字段名或表名。
如果必须使用关键字,可以通过在字段或表名前后添加反引号(`)来进行处理,如下所示:
综上所述,为了避免出现问题,建议尽量避免在数据库设计中使用关键字。
针对 MyBatis Plus 3.1.1 及更高版本出现的问题:
现象:在单元测试中没有问题,但是在启动服务器进行调试时出现该异常。
原因:在 3.1.1 版本及以后的版本中,针对字段缓存进行了优化,使用
.class
作为键来替换了原来的类名(className)。然而,当使用 dev-tools 时,可能会导致
.class
使用不同的类加载器加载,从而导致出现找不到属性的情况。
解决方案:移除 dev-tools 插件。这样可以避免使用不同的类加载器加载
.class
,从而解决该异常问题。
针对 MyBatis Plus 3.1.1 及更高版本出现的问题:
现象:在集成 Druid 数据源时,升级到 3.1.1 版本及之后的版本后,出现错误:java.sql.SQLFeatureNotSupportedException。而在 3.1.0 版本之前没有此问题。
原因:MyBatis Plus 3.1.1 版本及更高版本采用了新版 JDBC,对于新的日期类型(如 LocalDateTime)处理方式进行了升级。然而,Druid 在 1.1.21 版本之前不支持此特性,导致出现此异常。详细信息请参考 相关问题 。
解决方案:
如果您将 MyBatis Plus 从 3.1.0 及以下版本升级到较高版本,且遇到新日期类型(如 LocalDateTime)无法映射的报错,可能是由于以下原因:
MP_3.1.0 及之前版本依赖的是 MyBatis 3.5.0。而 MP_3.1.1 升级了 MyBatis 的依赖到 3.5.1,而在 MyBatis 3.5.1 中,新日期类型需要 JDBC 驱动支持 JDBC 4.2 API。
如果您的 JDBC 驱动版本不支持 JDBC 4.2 API,就会出现无法映射新日期类型的报错。
参考 MyBatis 官方博客 的内容:
解决方案:
如果您在将 Spring Boot 版本从 2.2.0 升级到更高版本时遇到此问题,可能是由于以下原因:
现象:在本地启动时没有问题,但是将打成 war 包部署到服务器时出现此问题。
原因:在 Spring Boot 2.2.0 中存在构造器注入的问题,导致 MyBatis 的私有构造器无法正确绑定属性,进而导致依赖 MyBatis 的框架(如 MyBatis Plus)报错。详细信息请参考 相关 issue 。此问题已在 Spring Boot 2.2.1 中得到修复。
解决方案:
现象:在开发工具中运行没有问题,但是将项目打包部署到服务器后,执行 Lambda 表达式时出现 ClassNotFoundException。
针对 MyBatis Plus 3.3.2 以下版本,如果在分离打包部署时出现 ClassNotFoundException 的问题,可能是因为在执行反序列化操作时,类加载器发生了错误。
解决方案:
您可以通过以下两种方式来启用 MyBatis 内部的日志记录:
方式一:
在您的
application.yml
或
application.properties
文件中添加以下配置:
这将使用 MyBatis 内置的 StdOutImpl 日志记录实现将日志输出到控制台。
方式二:
在您的
application.yml
或
application.properties
文件中增加日志级别配置,以指定特定包的日志级别。例如:
这将指定 com.baomidou.example.mapper 包下的日志级别为 debug。您可以根据需要调整级别。
通过以上配置,您可以启用 MyBatis 内部的日志记录,并根据需要调整日志级别。
如果您想要在更新操作时对某个字段进行自增操作,您可以使用 MyBatis Plus 提供的
Wrapper
进行更新。以下是一种可行的解决方案:
这样可以在更新时对字段进行自增操作。请注意,需要在
setSql
方法中直接指定 SQL 更新语句。
如果您想要全局处理数据库关键词,可以使用 MyBatis Plus 提供的全局配置。以下是配置示例(以 MySQL 为例):
这样配置后,MyBatis Plus 将会在生成 SQL 语句时,对数据库字段名称使用反引号(“)进行包裹,以确保不与数据库关键词冲突。
需要注意的是:
通过以上配置,您可以全局处理数据库关键词,确保生成的 SQL 语句不会受到关键词影响。
如果您想要在 XML 中根据数据库类型选择不同的 SQL 片段,您可以使用 MyBatis Plus 提供的
database-id
参数。以下是配置示例(以 MySQL 为例):
这样配置后,MyBatis Plus 将会在执行 SQL 语句时,根据
database-id
参数选择不同的 SQL 片段。
您可以根据不同的写法在 XML 中进行判断:
通过以上配置,您可以根据不同的数据库类型选择不同的 SQL 片段。
MyBatis Plus 不支持复合主键并强制使用唯一的 ID,这是出于以下考虑:
增加了表与表之间的相互依赖性:使用复合主键会使表与表之间的关系更加复杂,增加了维护和管理的难度。
增加了数据复杂的约束、规则:复合主键会增加数据的约束和规则,例如需要约束唯一性,而完全可以使用联合索引来实现。
增加了更新数据的限制:在更新数据时,需要更新所有复合主键的值,这增加了更新操作的限制和复杂性。
严重的数据冗余和更新异常问题:复合主键可能导致数据冗余和更新异常的问题,特别是在大型系统中,可能会出现更新异常的情况。
性能问题:使用复合主键时,查询某个 ID 时无法使用索引,会导致性能下降。
综上所述,虽然使用复合主键可以省去一个 ID 字段,但是这种做法的缺点大于优点,不建议也不推荐这样做。MyBatis Plus 坚持使用唯一的 ID,以保证数据管理的简单性、可维护性和性能。
初始化默认雪花ID导致
检查数据库连接池初始化
碰到过使用hikari在linux系统下启动缓慢
解决方案:
在java启动命令中指定 -Djava.security.egd=file:/dev/urandom把获取随机数的方式从 /dev/random改为/dev/urandom
示例: java -Djava.security.egd=file:/dev/urandom -jar xxxx.jar
解决方案:驱动连接去掉
rewriteBatchedStatements=true
配置