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

时间:2015-10-16 18:09:14

标签: java mysql jpa

我有一个如下所示的实体;

@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...
}

我需要相当于以下MySQL查询的JPA Criteria

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

所以我做了这样的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();

但它会在此行TypedQuery<CashHistory> query = em.createQuery(cq);引发以下异常。请参阅下面的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]

有人可以指点我可能做错了吗?

2 个答案:

答案 0 :(得分:0)

你必须这样做,并专注于命名和本机查询的以下链接 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);
          }

答案 1 :(得分:0)

您是否从Hibernate看到了这个问题?

我也试过你的代码,看起来它不适用于String类型的selectCase,而是使用Integer作为解决方法。

像这样的代码应该有用:

    func GetUserInfoByColumn(field string) *User, error {
query := fmt.Sprintf("SELECT user_id, name, email FROM users WHERE %s = ?", column)
    var u User
    err := db.QueryRow(query, value).Scan(&u.User_id, &u.Name, &u.Email)
    if err != nil {return nil, err}
    return &u, nil
    }