【问题标题】:Wild card search on Long value using Criteriabuilder query使用 Criteriabuilder 查询对 Long 值进行通配符搜索
【发布时间】:2014-04-23 10:43:13
【问题描述】:

我想对一个 Long 值(在实体类中)和 Integer 在数据库中的字段使用通配符搜索。这里的联系人是实体类,它具有字段:Id 作为实体类中的 Long 值和作为数据库中的 Integer .以下是代码。

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tuple> query = builder.createTupleQuery();
Root<Contact> root = query.from(Contact.class);
List<Predicate> predicates = new ArrayList<Predicate>();
if (searchCriteria.getContactId() != null) {
    if(searchCriteria.getContactId().contains("%")){                
       predicates.add(builder.like( 

       (root.get(Contact_.id)),-->Note this line

       builder.literal(searchCriteria.getContactId()+"%")));

        }
    }

这里builder.like不会接受root.get(Contact_.id),因为Contact_.id是长值。我们会在这里编译错误。这里searchCriteria.getContactId()是字符串值。

有没有办法将 root.get(Contact_.id) 转换为字符串类型?

public static volatile SingularAttribute<Contact, Long> id;

到目前为止,我已经尝试过

((Expression<String>)(root.get(Contact_.id).as(String.class).

但我收到查询语法异常。它无法将其转换为完美的语法。当我查看日志时,它给出的查询类似于 -> ( cast(generatedAlias0.id as varchar(255)) 但不是 ( cast(generatedAlias0.id as string)))

【问题讨论】:

  • 编译器会出错,因为CriteriaBuilder.lower() 方法只接受字符串表达式。您实际尝试做的是从长参数中获取小写。
  • @wypieprz 嗨,非常感谢您关注这个问题。有没有办法将这个 (root.get(Contact_.id)) 转换为字符串?
  • 你为什么需要这样的转换呢?您能否举例说明您要实现的目标,即使用 JPQL?恐怕我不明白这一点。
  • 这里我想对一个数字使用通配符搜索(实体类中的 Long 值和数据库中的 Integer)。这里的数字是 Contact_.id(长值)和 searchCriteria.getContactId( ) 将返回带有通配符的数字,它是一个字符串。这里它只允许字符串表达式。到目前为止,我已经尝试过 ((Expression)(root.get(Contact_.id).as(String.class) .但是我得到查询语法异常。它无法将其转换为完美的语法。它给出的查询类似于 -> ( cast(generatedAlias0.id as varchar(255)) 但不是 ( cast(generatedAlias0.id as string ))。
  • 如果您不清楚我的例外情况,请告诉我。提前谢谢您。

标签: hibernate jpa criteria-api


【解决方案1】:

当我使用类似的标签进行搜索时,我找到了一个很好的解决上述问题的方法,它只使用了条件生成器。我已经尝试过了,它工作正常。 我们可以在下面的链接中找到它。

JPA: How to perform a LIKE with a NUMBER column in a static JPA MetaModel?

【讨论】:

    【解决方案2】:

    JPA 指定的某些 CriteriaBuilder 的方法(如 notLike、concat、substring、trim、lower、upper、length、locate)只能处理字符串,因此拒绝整数表达式:

    predicates.add(
        Expression<Long> idExpr = root.get(Contact_.id);
        builder.like(idExpr), // error: Expression<String> is expected
        builder.literal(searchCriteria.getContactId() + "%")
    );
    

    要解决此问题,您可以尝试使用 Hibernate 扩展,例如:

    • HCQ(Hibernate Criteria Query)在原生 SQL 的帮助下
    Criteria c = session.createCriteria(Contact.class);
    c.add(Restrictions.sqlRestriction(" CAST(id AS varchar(255)) LIKE '1%'"));
    List<Contact> entities = c.list();
    
    • HQL(休眠查询语言)
    Query q = session.createQuery("FROM Contact c WHERE STR(c.id) LIKE '1%'");
    List<Contact> c= q.list();
    
    • SQL
    SQLQuery q2 = session.createSQLQuery("SELECT * FROM Contact " +
                                         "WHERE CAST(id AS varchar(255)) LIKE '1%'");
    List<Contact> entities = q.getResultList();
    

    看起来只有 HQL 有 STR() 表达式,或者我在 HCQ 中找不到等效项。无论如何,HQL 中使用的STR(c.id) 将被翻译成CAST(id AS VARCHAR(255)) 子句。

    【讨论】:

    • 它会像你说的那样工作 HCQ、HQL、SQl。非常感谢。同时我在搜索与 here 相同的主题后在 stackoverflow 中找到了。这里创建了一个可以工作的新类使用标准生成器很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多