You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot下使用Criteria查询PostgreSQL数组列包含指定值的方法

可以通过Criteria API实现该查询,具体实现方案如下:

前置依赖配置

首先要保证两个配置正确:

  • 项目已配置正确的PostgreSQL Hibernate方言,示例配置(application.yml):
spring:
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
  • 实体类User的groupIDs字段正确映射PostgreSQL的bigint[]数组类型,示例代码:
import jakarta.persistence.*;
import org.hibernate.type.LongArrayType;
import org.hibernate.annotations.Type;
import java.util.List;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // 映射PostgreSQL长整型数组列
    @Type(LongArrayType.class)
    @Column(name = "group_ids", columnDefinition = "bigint[]")
    private List<Long> groupIDs;
    
    // 省略其他字段、getter、setter
}

Criteria 查询实现

你可以通过调用PostgreSQL原生的数组包含函数arraycontains构造查询逻辑,示例代码如下:

import org.springframework.data.jpa.domain.Specification;
import jakarta.persistence.criteria.Expression;

// 你要筛选的目标groupID
Long targetGroupId = 1001L;

Specification<User> groupIdMatchSpec = (root, query, criteriaBuilder) -> {
    // 构造只包含目标groupID的单元素数组
    Expression<Long[]> targetGroupArray = criteriaBuilder.literal(new Long[]{targetGroupId});
    // 调用PostgreSQL原生arraycontains函数:判断表中groupIDs列是否包含目标数组的所有元素(此处就是单个目标ID)
    return criteriaBuilder.isTrue(
        criteriaBuilder.function(
            "arraycontains",
            Boolean.class,
            root.get("groupIDs"),
            targetGroupArray
        )
    );
};

// 调用JpaRepository查询,你的UserRepository需要继承JpaSpecificationExecutor<User>接口
List<User> matchedUsers = userRepository.findAll(groupIdMatchSpec);

上述代码最终生成的SQL等价于你预期的效果,实际执行的原生SQL为:

SELECT * FROM users WHERE arraycontains(group_ids, ARRAY[?]::bigint[])

和你需要的WHERE [targetGroupID] IN groupIDs逻辑完全一致。

注意事项

  • 如果你的Hibernate版本较低,也可以替换为使用ANY函数的写法,逻辑完全一致:
Specification<User> groupIdMatchSpec = (root, query, criteriaBuilder) -> {
    return criteriaBuilder.isTrue(
        criteriaBuilder.equal(
            criteriaBuilder.literal(targetGroupId),
            criteriaBuilder.function("ANY", Long.class, root.get("groupIDs"))
        )
    );
};
  • 不要用默认的JPA序列化方式存储数组,否则无法利用PostgreSQL的数组查询特性,效率会大幅降低。

内容的提问来源于stack exchange,提问作者Rishabh Ryber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:39:01