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);
            }
        });
    }
}
相关推荐
懒虫虫~2 小时前
基于SpringBoot利用死信队列解决RabbitMQ业务队列故障重试无效场景问题
spring boot·rabbitmq
struggle20252 小时前
RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
数据库·typescript·neo4j
伤不起bb3 小时前
Redis 哨兵模式
数据库·redis·缓存
卑微的Coder3 小时前
Redis Set集合命令、内部编码及应用场景(详细)
java·数据库·redis
2501_915373883 小时前
Redis线程安全深度解析:单线程模型的并发智慧
数据库·redis·安全
呼拉拉呼拉3 小时前
Redis知识体系
数据库·redis·缓存·知识体系
霖檬ing3 小时前
Redis——主从&哨兵配置
数据库·redis·缓存
CrissChan4 小时前
Pycharm 函数注释
java·前端·pycharm
启航挨踢4 小时前
java学习电子书推荐
java
wgslucky4 小时前
Dubbo报错:module java.base does not “opens java.lang“ to unnamed module
java·开发语言·dubbo