Набор JPA-фильтров Spring Data для перечисления значений с помощью @query или по имени функции - PullRequest
1 голос
/ 17 апреля 2020

У меня есть набор перечислений в качестве атрибута в MyClass (который является Entity) и я хочу отфильтровать строковые значения перечисления либо с помощью @Query, либо с помощью запроса имени функции JPA (не знаю правильного имени для него. ..)

My Enum:

public enum MyEnum {
    ONE("First string value"),
    TWO("Second string value"),
    THREE("Third string value");

    private MyEnum (String name) {
       this.name = name;
    }
    private final String name;

    @Override
    public String toString() {
        return name;
    }
}

Объявление набора перечислений в MyClass-Entity

@Size(min=1)
@ElementCollection (fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
private Set<MyEnum> myenums;

Таблица, которую он создает:

create table myclass_myenums (myclass_id bigint not null, myenum varchar(255));

@ Попытка запроса в моем репозитории.

@Query(value = "SELECT * from mytable t " +
            " left join myclass_myenums e ON e.myclass_id= t.id " +
            " WHERE " +
            " e.myenum LIKE CONCAT('%',:filtertext,'%') " 
            , nativeQuery = true)
    List<RisikoEntity> findbyFilter(@Param("filtertext") String filtertext);

Это работает, проблема в том, что он фильтрует по строкам "ONE", "TWO", "THREE", а не по "First string value" , "Второй ..." и так далее.


Альтернативная попытка с попыткой указать имя функции в моем репозитории:

List<MyClass> findByMyenumsContainsIgnoreCase(String filterstring)

---> Error: "Parameter value [%First%] did not match expected type [path.to.MyEnum (n/a)]"

Вторая попытка:

List<MyClass> findByMyenums_NameContainsIgnoreCase(String filterstring)

--> Error: "Illegal attempt to dereference path source [null] of basic type"

Что я делаю не так?

  1. Как отфильтровать фактические строковые значения перечисления в первом решении?
  2. Как отфильтровать наборы перечислений с помощью имени функции JPA?

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Если вы используете JPA 2.1, вы можете попытаться использовать его аннотацию @Converter, как предложено здесь , но это может привести к значительным накладным расходам, поскольку преобразованное значение String необходимо будет сохранить в вашей сущности:

@Converter(autoApply = true)
public class MyEnumConverter implements AttributeConverter<MyEnum, String> {

    @Override
    public String convertToDatabaseColumn(MyEnum myEnum) {
        if (myEnum == null) {
            return null;
        }
        return myEnum.toString();
    }

    @Override
    public MyEnum convertToEntityAttribute(String code) {
        if (code == null) {
            return null;
        }

        return Stream.of(MyEnum.values())
          .filter(m -> m.toString().equals(code))
          .findFirst()
          .orElseThrow(IllegalArgumentException::new);
    }
}
1 голос
/ 17 апреля 2020

Что ж, я бы сказал, что это невозможно, поскольку JPA не сохраняет строку name перечисления, а содержит фактическое имя перечисления.

Таким образом, ваша база данных должна содержать ONE или TWO вместо Первое строковое значение или Второе строковое значение внутри myenum столбца.

Единственный способ решить это сначала отфильтровать перечисление по коду, а затем найти по этому перечислению

...