7

私はタイプセーフティCriteriaQueryがJPA2.0をもたらすのが大好きですが、ボイラープレートコードも少しもたらします。たとえば、NamedEntityというエンティティがあり、これには単にidと "name"という文字列フィールドがあります(一意の制約がtrueに設定されていると仮定します)。NamedEntityManagerは次のようになります。

public class NamedEntityManager
{
    //inject using your framework
    EntityManager entityManager;

    //retrieve all existing entities of type NamedEntity from DB
    public Iterable<NamedEntity> queryAll()
    {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<NamedEntity> query = builder.createQuery(NamedEntity.class);
        return entityManager.createQuery(query).getResultList();
    }

    //retrieve a single entity of type NamedEntity from DB using specified name
    public NamedEntity queryByName(String name)
    {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<NamedEntity> query = builder.createQuery(NamedEntity.class);
        Root<NamedEntity> root = query.from(NamedEntity.class);
        query = query.where(root.<NamedEntity>get("name").in(name));

        //skipped the try/catch block for the sake of brevity
        return entityManager.createQuery(query).getSingleResult();
    }
}

同じコード行を各クエリメソッドにコピー/貼り付けしないようにするために、コードを凝縮する方法はありますか?おそらくどういうわけかCriteriaQueryオブジェクトを再利用しますか?

4

5 に答える 5

5

私はそのようなものを探していました.バックエンドとしてJPAを持つことができるQuerydsl(LGPLライセンス)を見ることができます.

私はまだそれを読んでいますが、彼らの例から、それはかなりきれいに見えます.

HQLQuery q = new HibernateQuery(session);
QCat cat = new QCat("cat"); // query type
List<Cat> cats = q.from(cat).where(cat.name.between("A", "B")).list(cat);
于 2011-01-11T17:18:06.200 に答える
4

JPA 2.1 では、おそらく JPQL と Criteria を混在させることができます。このようなアプローチでは、JPQL を使用してベース クエリを定義し、Criteria API を使用して小さなパーツを動的に追加できます。

その場合、API はそれほど冗長ではないと思います。使用する必要があるのは API のごく一部だけだからです。

于 2011-02-14T22:34:31.497 に答える
1

次に、JPA-2.0 MetaData モデルを使用します。 http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/

于 2010-11-05T07:04:27.893 に答える
1

コード量を減らす方法はないようです。型の安全性を確保するには、何かを犠牲にしなければならなかったと思います。

于 2010-12-23T16:39:25.447 に答える
0

この投稿はかなり古くなっていますが、単純なクエリ用に最近​​作成したものを追加したいと思います

    public static class Jpa2Whatsoever {

    private final EntityManager em;

    public class Jpa2WhatsoeverProgress<T> {

        private CriteriaQuery<T> cq;
        private List<Predicate> predicates = new ArrayList<>();
        private Root<T> root;

        public Jpa2WhatsoeverProgress(Class<T> type) {
            this.cq = em.getCriteriaBuilder().createQuery(type);
            this.root = cq.from(type);

        }

        public Jpa2WhatsoeverProgress<T> where(String attributeName, Object value) {

            Predicate equal = em.getCriteriaBuilder().equal(root.get(attributeName), value);

            predicates.add(equal);
            return this;
        }

        public List<T> getResultList() {
            Predicate[] predicatesArray = new Predicate[predicates.size()];
            TypedQuery<T> typedQuery = em.createQuery(cq.select(root).where(predicates.toArray(predicatesArray)));

            List<T> resultList = typedQuery.getResultList();

            return Collections.unmodifiableList(resultList);
        }

    }

    public Jpa2Whatsoever(EntityManager entityManager) {
        this.em = entityManager;
    }

    public <T> Jpa2WhatsoeverProgress<T> select(Class<T> type) {
        return new Jpa2WhatsoeverProgress<T>(type);
    }
}

こんな感じで使えます

List<MyEntity> matchingEntities = new Jpa2Whatsoever(entityManager).select(MyEntity.class).where("id", id).where("due", new Date()).getResultList();

結局これでやめました。主な理由は、クエリが 2 つしかなく、次のような必要なクエリ特性を取得するために DSL を拡張する必要があることがわかったからです。

  • より大きい、より小さい
  • メタモデルのサポート
  • QueryBuilder.currentDate()と同様。

whereさらに、実際にはより SQLly に対応しているのに、常に呼び出すのは見苦しいと思いandます。いずれにしても、非常に単純なクエリ API に興味がある場合は、試してみる価値があります。

ところで: 名前は忘れてください。これはプロトタイプであり、それ以上のものではありません。

于 2013-09-16T08:46:54.343 に答える