7

我喜欢 JPA 2.0 带来的类型安全CriteriaQuery,但它也带来了一些样板代码。例如,假设我有一个名为 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

我一直在寻找类似的东西,你可以看看Querydsl(LGPL 许可),它可以有 JPA 作为后端。

我还在阅读它,但从他们的例子来看,它看起来很干净。

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 和 Criterias。使用这种方法,您可以使用 JPQL 定义基本查询,然后使用 Criteria API 动态添加小部件。

我认为 API 将不那么冗长,因为您只需要使用它的一小部分。

于 2011-02-14T22:34:31.497 回答
1

然后使用 JPA-2.0 元数据模型。 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();

最后我停止了这个。主要是因为我看到我只有两个查询,我必须扩展 DSL 才能将所需的查询特征放入其中,例如

  • 大于,小于
  • 元模型支持
  • QueryBuilder.currentDate()等等。

此外,我发现总是调用它是丑陋的,where而它实际上对应于一个更 SQLly and。无论如何,如果有人对一个非常简单的查询 API 感兴趣,还是值得一试的。

顺便说一句:忘记名字,这是一个原型,仅此而已。

于 2013-09-16T08:46:54.343 回答