【问题标题】:Spring Data JPA filter set of enum values with @query or by function nameSpring Data JPA 使用@query 或函数名过滤枚举值集
【发布时间】:2020-07-30 14:27:08
【问题描述】:

我有一组枚举作为 MyClass(它是一个实体)中的一个属性,并且想使用 @Query 或使用 JPA 函数名称查询过滤枚举的字符串值(不知道它的正确名称。 ..) .

我的枚举:

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 在我的存储库中尝试。

@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”,而不是“第一个字符串值”、“第二个......”等等。


在我的存储库中尝试使用函数名事物的替代尝试:

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 函数名称的枚举集?

【问题讨论】:

  • 您的枚举代码似乎无法编译。您必须有其他字段来设置您的描述,
  • 如果您的枚举的表描述中没有join_id,而您有myclass_id,那么JOIN 如何在您的查询中工作?
  • 对不起,我忘记了例子中的构造函数,你是这个意思吗?你是对的,我不想给出我所有的实际代码,所以我不得不为 MCVE 重命名一些东西,我编辑了它。
  • 我不认为这是可能的,这里的枚举不是一个字符串,就像期望的字符串表达式
  • 是的,构造函数

标签: java sql jpa enums spring-data-jpa


【解决方案1】:

如果您使用 JPA 2.1,您可以尝试将其 @Converter 注释用作 suggested here 但这可能会产生大量开销,因为转换后的字符串值必须存储在您的实体中:

@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);
    }
}

【讨论】:

  • 我试过这个,但它仍然过滤到“ONE”而不是“第一个字符串值” - 我还尝试将 @Convert (converter = MyEnumConverter.class) 添加到实体字段以防自动应用不起作用,但结果相同:/
  • 想通了 - 我需要用 @Convert 替换 @Enumerated(EnumType.STRING) (顺便说一句,自动应用由于某种原因不起作用)。谢谢!
【解决方案2】:

我想说这是不可能的,因为 JPA 不会保留枚举的 name 字符串,而是保留枚举的实际名称。

所以你的数据库应该包含 ONE 或 TWO 而不是 First string value 或 Second string value 在 @ 987654322@专栏。

解决这个问题的唯一方法是首先通过代码过滤枚举,然后通过该枚举查找

【讨论】:

  • 因此,如果我理解正确,我将不得不在第二列中使用“第一个字符串值”在 ONE / TWO / THREE 上加入另一个表,并针对 @Query 解决方案过滤该列?
  • 你可以这样做,是的,创建一个包含你的枚举的表
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 2019-04-22
相关资源
最近更新 更多