解决 Spring Boot + MyBatis 项目迁移到 PostgreSQL 后的数据类型不匹配问题

解决 Spring Boot + MyBatis 项目迁移到 PostgreSQL 后的数据类型不匹配问题

项目场景

在当前的项目开发中,我们采用了 Spring Boot 作为后端开发框架,结合 MyBatis 进行数据库操作。起初,项目使用的是 MySQL 数据库,但随着业务的发展和对数据库功能的更高要求,我们决定将数据库迁移到 PostgreSQL。

Spring Boot 以其便捷的开发特性和强大的自动化配置能力,极大地提高了开发效率;MyBatis 则凭借其灵活的 SQL 映射和执行机制,让我们能够更精细地控制数据库操作。然而,当完成数据库从 MySQL 到 PostgreSQL 的迁移后,我们发现某些操作出现了异常,这主要是由于两种数据库在数据类型处理以及操作符的支持上存在差异,导致原有的 SQL 语句在 PostgreSQL 中无法正常执行。

问题描述

在项目中执行数据库查询时,抛出了如下异常:

复制代码
org.springframework.jdbc.BadSqlGrammarException: 
Error querying database.  Cause: org.postgresql.util.PSQLException: ERROR: operator does not exist: boolean = integer
  建议:No operator matches the given name and argument types. You might need to add explicit type casts.
  位置:64
The error may exist in cn/iocoder/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java (best guess)
The error may involve defaultParameterMap
The error occurred while setting parameters

从异常信息可以看出,原因是在 SQL 语句里用布尔类型的字段 deleted 和整数 0 进行比较,而 PostgreSQL 没有定义这样的操作符。在 Spring Boot + MyBatis 的项目结构中,这样的异常通常会影响到数据的查询和处理,进而导致业务逻辑无法正常执行。

原因分析

在 PostgreSQL 中,布尔类型(boolean)和整数类型(integer)是不同的数据类型,不能直接使用 = 操作符进行比较。deleted 字段一般是布尔类型,true 代表已删除,false 代表未删除,而在 SQL 中使用整数 0 与之比较,从而引发错误。这是因为 MySQL 和 PostgreSQL 对数据类型的处理方式不同,MySQL 在某些情况下可能会进行隐式类型转换,而 PostgreSQL 则更加严格,要求数据类型必须严格匹配。

解决方案

修改 SQL 查询语句

把整数 0 替换成布尔值 false,因为在 PostgreSQL 里,false 通常用于表示逻辑上的 "未删除" 状态。在 MyBatis 的映射文件中,对应的 SQL 语句可以修改为:

xml 复制代码
<select id="countNotDeletedOrders" resultType="java.lang.Integer">
    SELECT COUNT(*) AS total FROM erp_purchase_order t WHERE t.deleted = false
</select>

如果使用注解方式的 MyBatis 查询,Java 方法中的 SQL 语句可以修改为:

java 复制代码
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Repository
public interface ErpPurchaseOrderMapper {

    @Select("SELECT COUNT(*) AS total FROM erp_purchase_order t WHERE t.deleted = false")
    Integer countNotDeletedOrders();
}

当然以上可能还是有问题那就简单粗暴

  • 当试图将 boolean 类型的数据直接转换为 smallint(对应 SQL 里的 int2)类型时,PostgreSQL 不支持这种直接的类型转换。可以采用先移除默认值,修改类型后再重新设置的方法,示例 SQL 代码如下:
sql 复制代码
-- 移除默认值
ALTER TABLE erp_purchase_order
ALTER COLUMN "deleted" DROP DEFAULT;

-- 修改列的数据类型,使用 CASE 语句进行转换
ALTER TABLE erp_purchase_order
ALTER COLUMN "deleted" TYPE smallint
USING CASE WHEN "deleted" THEN 1 ELSE 0 END;

-- 设置新的 smallint 类型的默认值
ALTER TABLE erp_purchase_order
ALTER COLUMN "deleted" SET DEFAULT 0;

注意事项

  • 数据备份:在执行这些操作之前,务必备份数据库,以防数据丢失或损坏。由于 Spring Boot 项目的数据通常与业务紧密相关,数据丢失可能会导致严重的业务问题。
  • 权限问题:要确保你有足够的权限来修改数据库中的表结构。在团队开发环境中,需要与数据库管理员协调好权限分配。
  • 外键和约束 :如果 deleted 列涉及外键约束或其他约束,需要先处理这些约束,否则可能会导致操作失败。可以在删除列之前禁用相关约束,操作完成后再重新启用。
  • 性能影响:对于大型表,删除和添加列以及更新数据可能会花费较长时间,并且会产生较大的事务日志,建议在低峰期进行操作,以免影响项目的正常运行。

通过以上方法,可以有效解决 Spring Boot + MyBatis 项目迁移到 PostgreSQL 后因数据类型不匹配而引发的问题。希望这些解决方案能对你有所帮助,让你的项目在新的数据库环境中稳定运行。

相关推荐
曲幽5 小时前
我用了FastApiAdmin后,连夜把踩过的坑都整理出来了
redis·python·postgresql·vue3·fastapi·web·sqlalchemy·admin·fastapiadmin
Muscleheng9 小时前
Navicat连接postgresql时出现‘datlastsysoid does not exist‘报错
数据库·postgresql
写了20年代码的老程序员12 小时前
写了 20 年 Java,我受够了 MyBatis 的 4 个瞬间
mybatis·orm
jameslogo12 小时前
如何用RocketMQTemplate发送事务消息
java·spring boot·rocketmq
Gauss松鼠会13 小时前
GaussDB(DWS) 日常维护命令
服务器·数据库·postgresql·性能优化·gaussdb·经验总结
无关868814 小时前
Spring Boot 项目标准化部署打包实战
java·spring boot·后端
jay神14 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
阿丰资源14 小时前
基于Spring Boot的酒店客房管理系统
java·spring boot·后端
IvorySQL15 小时前
开源共建分论坛圆桌讨论:如何真正融入 PostgreSQL 社区?
postgresql·开源·区块链
zzqssliu15 小时前
SpringBoot框架搭建跨境独立站|Taocarts代购系统订单模块深度开发
java·spring boot·后端