JPA规范可基于jsonb映射中的键过滤条目

时间:2020-01-07 12:35:21

标签: spring-boot jpa

我的实体如下:

@Entity
@Getter
@Setter
@NoArgsConstructor
@TypeDefs({
        @TypeDef(name = "jsonb", typeClass = JsonbType.class)
})
public class Entity extends BasePersistableEntity<String> implements Serializable {

    public static final String FIELD_NAME_SERVICES = "services";
    public static final String FIELD_NAME_ORG_ID = "orgId";

    @Column
    public String orgId;

    @Column
    @Type(type = "jsonb")
    public Map<String, String> services;
}

我想编写一个查询,以从Postgres数据库中获取属于orgId并在其服务映射中具有service的所有实体。

例如类似

select * from Entity where entity.ordId='abc' and 'xyz' in entity.services.keyset();

当前,我编写的解决方案如下:

@Override
public List<Entity> getEntitiesWithOrgIdAndService(String orgId, String service) {
    return entityRepository.findEntityByOrgId(orgId).stream()
              .filter(entity -> entity.services.containsKey(service)).collect(Collectors.toList());
}

相反,我想在从数据库中获取它时对其进行过滤。我该如何使用JPA规范?

如下所示:

@Override
public List<Proxy> getEntitiesWithOrgIdAndService(String orgId, String service) {
     return proxyRepository.findAll(getSpecificationForEntity(orgId, service));
}

private Specification<Proxy> getSpecificationForProxyForEntity(String orgId, String service) {
     return (Specification<Proxy>) (root, query, builder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Predicate orgIdPredicate =
                    builder.equal(root.get(Entity.FIELD_NAME_ORG_ID), orgId);
            // FIX NEEDED 
            /* Predicate servicePredicate =
                    builder.equal(builder.function("jsonb_extract_path_text",
                            String.class, root.<String>get(Entity.FIELD_NAME_SERVICES), service); */
            Predicate orgIdServicePredicate = builder.and(orgIdPredicate, servicePredicate);
            predicates.add(orgIdServicePredicate);
            return builder.and(predicates.toArray(new Predicate[0]));
        };
}

1 个答案:

答案 0 :(得分:0)

以下更改为我解决了此问题。

Predicate servicePredicate =
                    builder.equal(builder.function(Constants.FUNCTION_JSONB_EXTRACT_PATH_TEXT,
                            String.class, root.<String>get(Proxy.FIELD_NAME_SERVICES),
                            builder.literal(service)), String.valueOf(true));