【问题标题】:Perform JPA query with LIKE operator on entity with enum (EnumType.STRING)使用 LIKE 运算符对具有枚举 (EnumType.STRING) 的实体执行 JPA 查询
【发布时间】:2012-06-05 06:10:41
【问题描述】:

我能够存储、检索和查询枚举类型的实体(使用 JPA/Hibernate)。枚举字段使用@Enumerated(EnumType.STRING) 进行注释。

是否可以做"SELECT a FROM MyEntity a WHERE a.myEnum LIKE :param"之类的事情?

想法是让它匹配枚举值字符串(在 DB 中)匹配“SYSTEM_%”或“BUSINESS_%”等模式的任何实体。

感谢您的帮助。

--- 更新:

当我尝试用这个查询时:

`@Query("SELECT e FROM MyEntity e WHERE e.myEnum LIKE :value")`

使用值(表示匹配任何内容...):

%%

我得到了这个例外:

  Caused by: java.lang.IllegalArgumentException: Parameter value [%%] did not match expected type [mypackage.MyEntity$MyEnum]
        at org.hibernate.ejb.AbstractQueryImpl.validateParameterBinding(AbstractQueryImpl.java:370)
        at org.hibernate.ejb.AbstractQueryImpl.registerParameterBinding(AbstractQueryImpl.java:343)
        at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:374)
        at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:71)

【问题讨论】:

  • 您确定要使用 like there 而不是 =?
  • 是的,我是。这有点奇怪,但目的是提供枚举字符串值(存储在 db 中)的“部分值的简单搜索过滤器”。因此,如果用户键入“system”,它应该只返回以“system***”开头的枚举。
  • 我已经更新了我的答案。我已经对此进行了测试,它完全符合您的要求。

标签: java jpa


【解决方案1】:

我遇到了同样的问题,我做了以下事情:

  • 定义第二个属性映射到相同的 db 列
  • 该属性的类型是字符串
  • 它既不可更新也不可插入
  • 调整枚举属性的set方法
  • 将 String 属性设为只读属性
    @Column(name = "status")
    @Enumerated(EnumType.STRING)
    private StatusEnum status;

    public void setStatus(StatusEnum status) {
        this.status = status;
        this.statusString = status.toString();
    }
    
    @Column(name ="status", updatable = false, insertable = false)
    private String statusString;

现在您可以对 statusString 使用 'like' 进行查询:

TypedQuery<MyEntity> query = 
    em.createQuery("select e from MyEntity e where e.statusString like 'CLOSED%', MyEntity.class);

【讨论】:

    【解决方案2】:

    作为一种解决方法,您可以通过将模式连接到查询来构建查询。

    em.createQuery("SELECT e FROM MyEntity e WHERE e.myEnum LIKE '" + pattern +"'")
    

    它适用于 Hibernate 和 Eclipselink。

    但是不要尝试使用由用户输入生成的pattern,因为以这种方式构造查询很容易受到 sql 注入攻击。

    【讨论】:

    • 用 Hibernate 4.3.6.Final 和 Eclipselink 2.5.1 测试
    【解决方案3】:

    据说在org.springframework.orm.hibernate3.HibernateTemplate中有一个快捷方式:

    protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value)
            throws HibernateException {
    
        if (value instanceof Collection) {
            queryObject.setParameterList(paramName, (Collection) value);
        }
        else if (value instanceof Object[]) {
            queryObject.setParameterList(paramName, (Object[]) value);
        }
        else {
            queryObject.setParameter(paramName, value);
        }
    }
    

    如果有额外的 else if (value instanceoff String)...

    【讨论】:

      【解决方案4】:

      当然。只需使用query.setString("param", "BUSINESS_%");。请注意,使用 setParameter() 而不是 setString() 会引发 ClassCastException,因为 Hibernate 会尝试将其强制转换为枚举,但 setString() 完全符合您的要求。

      【讨论】:

      • 我明白了,所以这可能有效,但我现在无法轻松“测试”这个,因为我正在使用 Spring Data JPA > JPA > Hibernate。请记住,如果我得到验证,将来会勾选您的答案。谢谢!
      • 据说在hibernateTemplat中有一个快捷方式:
      • setString 不再存在
      猜你喜欢
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      • 2013-03-05
      • 2013-01-04
      • 2012-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多