2017-01-24 12 views
3

Iは、このクラスを有するオプションパラメータJPA 2.1

@Entity 
public class Message { 

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private long id; 

    @Column(nullable = false) 
    private String mobile; 

    @Column(nullable = false) 
    private String message; 

    @Column(nullable = false) 
    private Lang lang; 

    @Column(nullable = false) 
    private int status; 

    @Column(nullable = false) 
    private Calendar creationDate; 
    ... 
} 

及びIは、フォームから任意のパラメータでテーブルを照会できるようにしたいです。 JPA 2.1とHibernateを使用しています。複数のクエリステートメントを使わずに、または私のアプリケーションを休止状態にするか、または私が使用している特定のデータベースに強固に結合することなく、これを行う方法はありますか?ここで

は、私が使用している形です:

<form action="${pageContext.request.contextPath}/search"> 
<label>From</label> 
<input type="datetime" placeholder="dd/mm/yy hh/mm" name="from" required> 
<label>To</label> 
<input type="datetime" placeholder="dd/mm/yy hh/mm" name="to" required> 
<select name="lang"> 
    <option value="english">English</option> 
    <option value="arabic">Arabic</option> 
</select> 
<input type="tel" placeholder="Recipient" name="recipient"> 
<select name="status"> 
    <option value="new">New</option> 
    <option value="picked">Picked</option> 
    <option value="sent">Sent</option> 
    <option value="rejected">Rejected</option> 
</select> 
<input type="submit" value="Search"> 

UPDATE :::::::::::::::::::::::::

public List<Message> getMessages(Calendar fromDate, Calendar toDate, String lang, String recipient, String status) { 
    /*TypedQuery<Message> query = em.createQuery(
      "SELECT e FROM Message e WHERE e.creationDate BETWEEN :fromDate AND :toDate", Message.class); 
    query.setParameter("fromDate", fromDate); 
    query.setParameter("toDate", toDate); 
    List<Message> list = query.getResultList(); 
    return list;*/ 

    List<Predicate> predicates = new ArrayList<>(); 

    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Message> query = cb.createQuery(Message.class); 
    Root<Message> root = query.from(Message.class); 

    predicates.add(cb.between(root.get("creationDate"), fromDate, toDate)); 

    if (lang != null && !lang.equalsIgnoreCase("any")) { 
      predicates.add(cb.equal(root.get("lang"), lang)); 
     } 

    if (recipient != null && !recipient.equals("")) { 
      predicates.add(cb.equal(root.get("mobile"), recipient)); 
     } 

    if (status != null && !status.equalsIgnoreCase("any")) { 
      predicates.add(cb.equal(root.get("mobile"), recipient)); 
     } 

    query.where(cb.and(predicates.toArray(new Predicate[predicates.size()]))); 
    List<Message> list = em.createQuery(query).getResultList(); 

    return list; 
} 

が、私は次のエラー取得しています:

を:::

は、私はこれを試してみました210
java.lang.IllegalArgumentException: Parameter value [0] did not match expected type [entity.Lang (n/a)] 
at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:897) 
at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:61) 
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:235) 
at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:638) 
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:163) 
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:32) 
at org.hibernate.jpa.criteria.compile.CriteriaCompiler$1$1.bind(CriteriaCompiler.java:109) 
at org.hibernate.jpa.criteria.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:369) 
at org.hibernate.jpa.criteria.compile.CriteriaCompiler.compile(CriteriaCompiler.java:130) 
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:699) 
at dao.MessageDAO.getMessages(MessageDAO.java:63) 
+1

は、その文字列表現、私は今それをしようとしている –

答えて

2

短い回答:はい。あなたのニーズを満たすクエリを構築するために、ハイバネート固有のクラスを使う必要はありません。

ただし、クエリを作成する前にオプションのパラメータを除外したい場合があります。 telnull/emptyの場合は、おそらくクエリに含めることは望ましくありません。だから、それをクエリに追加しないでください。 the Java EE persistence tutorialCriteriaBuilder javadocをご覧になり、必要な方法でTypedQueryを構築してください。

擬似コード(明確にテストされていない...しかし、私はあなたのアイデアを得る願っています):

List<Predicate> predicates = ... 
CriteriaBuilder cb = ... 
Root<?> table = ... 
if (isNotBlank(tel)) { 
    predicates.add(cb.equal(table.get("tel"), tel)); 
} 
if (isNotBlank(...)) { 
    predicates.add(cb.like(table.get("..."), ...)); 
} 
... 
query.where(cb.and(predicates.toArray(Predicate[]::new))); 

たぶん、また次のことができます:ここでReally dynamic JPA CriteriaBuilder

+0

ありがとうをしませLang.valueOf(LANG)を使用しますので、ラングオブジェクトを渡しているしてみてください。 –

0

あなたがベースの更新方法をより良い方法を持っていますオプションのパラメータ

public int updateMyEntity(String value1, String value2){ 

    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaUpdate<MyEntity> cu = cb.createCriteriaUpdate(MyEntity.class); 
    Root<MyEntity> root = cu.from(MyEntity.class); 

    if (value1 != null) { 
     cu.where(cb.equal(root.get(MyEntity.value1), value1)); 
    } 

    if (value2 != null) { 
     cu.where(cb.equal(root.get(MyEntity.value2), value2)); 
    } 

    // set 
    cu.set(MyEntity_.isAvailable, true); 

    return em.createQuery(cu).executeUpdate(); 
} 
関連する問題