PostgreSQL+MybatisPlus,设置逻辑删除字段后查询出现:操作符不存在: boolean = integer 错误

项目场景:

Springboot2+PostgreSQL+MybatisPlus


问题描述

在建立Entity时添加了逻辑删除字段:

java 复制代码
@Data
public class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    // 主键ID
    @TableId
    private String id;

    // 删除标识 (逻辑删除字段)
    @TableLogic
    @TableField(fill = FieldFill.INSERT) // 默认插入时设置为 false
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private Boolean deleted = false;

    // 创建时间
    @TableField(fill = FieldFill.INSERT) // 插入时自动填充
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private LocalDateTime createTime;

    // 更新时间
    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时自动填充
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private LocalDateTime updateTime;
}

数据表建立:

sql 复制代码
create table tb_user
(
    id          varchar(255) not null
        primary key,
    username    varchar(255) not null
        unique,
    password    varchar(255) not null,
    deleted     boolean   default false,
    create_time timestamp default CURRENT_TIMESTAMP,
    update_time timestamp default CURRENT_TIMESTAMP
);

查询语句:

java 复制代码
 if (userMapper.selectCount(new QueryWrapper<TbUser>()
                .eq("username", tbUser.getUsername())) > 0) {
            throw new ViewException(ViewExceptionType.DATA_ALREADY_EXISTS, "用户名已存在");
        }

随后在插入数据的时候报错:

复制代码
### Error querying database.  Cause: org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55
### The error may exist in com/sgcchg/data/mapper/UserMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT COUNT( * ) AS total FROM tb_user  WHERE deleted=0     AND (username = ?)
### Cause: org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55
; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55

org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database.  Cause: org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55
### The error may exist in com/sgcchg/data/mapper/UserMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT COUNT( * ) AS total FROM tb_user  WHERE deleted=0     AND (username = ?)
### Cause: org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55
; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: 错误: 操作符不存在: boolean = integer
  建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换.
  位置:55
	at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101) ~[spring-jdbc-5.3.22.jar:5.3.22]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) ~[spring-jdbc-5.3.22.jar:5.3.22]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79) ~[spring-jdbc-5.3.22.jar:5.3.22]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79) ~[spring-jdbc-5.3.22.jar:5.3.22]
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92) ~[mybatis-spring-2.1.2.jar:2.1.2]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:439) ~[mybatis-spring-2.1.2.jar:2.1.2]
	at com.sun.proxy.$Proxy98.selectOne(Unknown Source) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:160) ~[mybatis-spring-2.1.2.jar:2.1.2]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:87) ~[mybatis-plus-core-3.5.5.jar:3.5.5]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:152) ~[mybatis-plus-core-3.5.5.jar:3.5.5]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.5.5.jar:3.5.5]
	at com.sun.proxy.$Proxy106.selectCount(Unknown Source) ~[na:na]
	at com.sgcchg.business.impl.user.UserServiceImpl.addUser(UserServiceImpl.java:72) ~[classes/:na]

原因分析:

数据库字段是boolean。但是在wrapper查询的时候没有指定deleted,查看报错信息发现最终底层查询会有deleted=0。

原因为:MyBatis-Plus 提供了逻辑删除功能,可以自动在查询条件中添加逻辑删除字段的判断条件。如果 deleted 字段被配置为逻辑删除字段,那么 MyBatis-Plus 在查询时会自动将 deleted = false 这个条件添加到查询语句中。

解决方案:

在 application.yml 或 application.properties中进行以下配置:

bash 复制代码
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted   # 逻辑删除字段名
      logic-not-delete-value: 0     # 表示未删除的值
      logic-delete-value: 1         # 表示已删除的值

bash 复制代码
mybatis-plus.global-config.db-config.logic-delete-field=deleted
mybatis-plus.global-config.db-config.logic-delete-value=true
mybatis-plus.global-config.db-config.logic-not-delete-value=false

即可解决

还有一种方法是修改配置文件:

java 复制代码
@Configuration
public class MybatisPlusConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 配置逻辑删除
        LogicSqlInjector logicSqlInjector = new LogicSqlInjector();
        interceptor.addInnerInterceptor(logicSqlInjector);
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setObjectWrapperFactory(new DefaultObjectWrapperFactory() {
            @Override
            public boolean hasWrapperFor(Object object) {
                return object instanceof Boolean;
            }

            @Override
            public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
                return new BooleanObjectWrapper(metaObject, (Boolean) object);
            }
        });
    }
}
相关推荐
ClouGence1 小时前
CloudCanal + Paimon + SelectDB 从 0 到 1 构建实时湖仓
数据库
渣哥1 小时前
原来 Java 里线程安全集合有这么多种
java
间彧1 小时前
Spring Boot集成Spring Security完整指南
java
间彧1 小时前
Spring Secutiy基本原理及工作流程
java
Java水解2 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆5 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学5 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole5 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊5 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端