简体   繁体   English

如何正确地将此SQL case语句转换为JPA Criteria Query

[英]How to properly convert this SQL case statement to JPA Criteria Query

I have an entity as shown below; 我有一个实体,如下所示;

@Entity
@Table(name="cashhistory")  
@NamedQueries({
    @NamedQuery(name="CashHistory.findAll", query="SELECT c FROM CashHistory c")
})

public class CashHistory implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    private int id;

    @Column(nullable=false)
    private boolean funded;

    //... other fields
    //... getters & setters...
}

I need the JPA Criteria equivalent of the following MySQL query 我需要等效于以下MySQL查询的JPA标准

select * from cashhistory c 
where (case when (c.funded = true) then 'SUCCESS' else 'FAILED' end) like '%SUCC%'

So I made a JPA Criteria API expression like this; 因此,我做了这样的JPA Criteria API表达式;

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<CashHistory> cq = cb.createQuery(CashHistory.class);
Root<CashHistory> entity = cq.from(CashHistory.class);
cq.select(entity);

Expression<String> expr = cb.selectCase()
    .when(cb.equal(entity.<Boolean>get("funded"), cb.literal(true)), cb.literal("SUCCESS"))
    .otherwise(cb.literal("FAILED")).as(String.class);

cq.where(cb.like(expr, "%SUCC%"));
TypedQuery<CashHistory> query = em.createQuery(cq);
return query.getResultList();

But it throws the following exception at this line TypedQuery<CashHistory> query = em.createQuery(cq); 但它在此行引发以下异常TypedQuery<CashHistory> query = em.createQuery(cq); . See the StackTrace below; 参见下面的StackTrace;

Caused by: java.lang.IllegalArgumentException: Parameter value [%SUCC%] did not match expected type [java.lang.Character]
    at org.hibernate.ejb.AbstractQueryImpl.validateParameterBinding(AbstractQueryImpl.java:370) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.AbstractQueryImpl.registerParameterBinding(AbstractQueryImpl.java:343) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:370) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler$1$1.bind(CriteriaQueryCompiler.java:194) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler.compile(CriteriaQueryCompiler.java:247) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:622) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.jboss.as.jpa.container.AbstractEntityManager.createQuery(AbstractEntityManager.java:96) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]

Can someone please point me to where I'm probably doing something wrong? 有人可以指出我可能做错了什么吗?

you have to do like this and concentrate on the following link for named and native query http://www.tutorialspoint.com/jpa/jpa_jpql.htm 您必须这样做,并专注于以下链接以进行命名查询和本机查询http://www.tutorialspoint.com/jpa/jpa_jpql.htm

EntityManagerFactory emfactory = Persistence.createEntityManagerFactory(  "Eclipselink_JPA" );
          EntityManager entitymanager = emfactory.createEntityManager();
          Query query = entitymanager.
          createQuery("select c from cashhistory c where (case when (c.funded = true) then 'SUCCESS' else 'FAILED' end) like '%SUCC%'");
          List<String> list = query.getResultList();

          for(String e:list) {
             System.out.println("Object :"+e);
          }

Have you seen this issue from Hibernate ? 您是否从Hibernate看到了这个问题?

I also tried your code and it looks like it won't work with String typed selectCase, and instead use Integer as workaround. 我还尝试了您的代码,它看起来不适用于String类型的selectCase,而是使用Integer作为解决方法。

Something like this code should work: 像这样的代码应该可以工作:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<CashHistory> cq = cb.createQuery(CashHistory.class);
    Root<CashHistory> entity = cq.from(CashHistory.class);
    cq.select(entity);

    Expression<Integer> caseExpr = cb.selectCase()
            .when(cb.equal(entity.get("funded"), true), 1)
            .otherwise(2).as(Integer.class);


    cq.where(cb.equal(caseExpr, 1));
    TypedQuery<CashHistory> query = em.createQuery(cq);
    query.getResultList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM