Как использовать одну спецификацию jpa для нескольких объектов - PullRequest
0 голосов
/ 22 октября 2019

Мне нужно написать несколько критериев для разных сущностей и нескольких столбцов. В настоящее время у меня есть несколько классов спецификации, один для сущности ekach. Как я могу сделать это единой спецификацией jpa, общей для всех сущностей.

1 Ответ

0 голосов
/ 31 октября 2019

Если вы пытаетесь применить множественные спецификации к разным объектам для получения результата, вы не сможете смешивать разные типы спецификаций, поскольку спецификации привязаны к объектам, которые вы пытаетесь получить из вашего запроса. Однако вы можете достичь такого результата, объединяя спецификации для сущности, которую вы пытаетесь получить, используя соединения.

Допустим, у вас есть сущность Product, которая содержит сущности Field с атрибутом «name», которые сами содержатОбъекты FieldValue с атрибутами «значение». Вы хотите получить продукт по имени поля, имеющему одно или несколько значений FieldValues. Вот фрагмент кода, который даст вам желаемый результат:

Specification<Product> fieldNameHavingValues(String fieldName, List<String> fieldValues) {
    return ((root, criteriaQuery, criteriaBuilder) -> {
        if (fieldName == null || fieldValues == null || fieldValues.isEmpty()) {
            return null;
        }
        Join<Product, Field> fieldJoin = root.join(Product_.fields); // First join on Field table
        Predicate namePredicate = criteriaBuilder.equal(fieldJoin.get(Field_.name), fieldName); // Assert that the field name has the desired one
        Join<Field, FieldValue> valueJoin = fieldJoin.join(Field_.fieldValues); // Join the third table, i.e. the FieldValue table
        Expression<String> expression = valueJoin.get(FieldValue_.value); 
        Predicate valuePredicate = expression.in(fieldValues); // Assert that the values are in the given collection
        return criteriaBuilder.and(namePredicate, valuePredicate); // Return the combined predicate

    });
}

List<Product> prods = productRepository.findAll(fieldNameHavingValues("colors", Arrays.asList("blue", "orange")));

Этот конкретный пример будет получать список всех продуктов, имеющих поле с именем "colors", содержащее либо значение "blue", либо "orange".

Обратите внимание, что вам придется расширять свой репозиторий JpaSpecificationExecutor:

public interface ProductRepository extends JpaRepository<Product, Long>, JpaSpecificationExecutor<Product> 

и генерировать метамодели, например, используя Maven:

<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jpamodelgen</artifactId>
        <version>5.3.7.Final</version>
        <scope>provided</scope>
</dependency> 

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...