解决 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 后因数据类型不匹配而引发的问题。希望这些解决方案能对你有所帮助,让你的项目在新的数据库环境中稳定运行。

相关推荐
梁云亮13 分钟前
Spring Boot + Thymeleaf 防重复提交
spring boot·防抖·防重复提交
XMYX-07 小时前
Spring Boot + Prometheus 实现应用监控(基于 Actuator 和 Micrometer)
spring boot·后端·prometheus
@yanyu6669 小时前
springboot实现查询学生
java·spring boot·后端
酷爱码9 小时前
Spring Boot项目中JSON解析库的深度解析与应用实践
spring boot·后端·json
bing_15810 小时前
跨多个微服务使用 Redis 共享数据时,如何管理数据一致性?
redis·微服务·mybatis
java干货10 小时前
虚拟线程与消息队列:Spring Boot 3.5 中异步架构的演进与选择
spring boot·后端·架构
文牧之11 小时前
PostgreSQL 的扩展pg_freespacemap
运维·数据库·postgresql
爱宇阳12 小时前
使用 Docker Compose 从零部署 TeamCity + PostgreSQL(详细新手教程)
docker·postgresql·容器
武昌库里写JAVA13 小时前
iview Switch Tabs TabPane 使用提示Maximum call stack size exceeded堆栈溢出
java·开发语言·spring boot·学习·课程设计