JPA Спецификация для фильтрации записей на основе ключа в карте JSONB - PullRequest
0 голосов
/ 07 января 2020

У меня есть сущность следующим образом:

@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 голосов
/ 08 января 2020

Следующее изменение решило проблему для меня.

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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...