Есть ли способ уменьшить количество кода котельной пластины, связанного с CriteriaQuery (в JPA 2.0)? - PullRequest
7 голосов
/ 14 июня 2010

Мне нравится тип безопасности CriteriaQuery с JPA 2.0, но также с небольшим количеством кода для котельной пластины. Например, допустим, у меня есть сущность с именем NamedEntity, которая просто имеет идентификатор и поле String с именем «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?

Ответы [ 5 ]

4 голосов
/ 15 февраля 2011

В JPA 2.1, наиболее вероятно, будет возможно смешать JPQL и Критерии.При таком подходе вы можете определить базовый запрос с помощью JPQL, а затем использовать Criteria API для динамического добавления небольших частей.

Я полагаю, что API будет менее многословным, поскольку вам нужно использовать только его небольшие части..

4 голосов
/ 11 января 2011

Я искал что-то подобное, вы можете взглянуть на 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);
1 голос
/ 05 ноября 2010

Затем используйте модель метаданных JPA-2.0. http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/

0 голосов
/ 16 сентября 2013

Устаревший, этот пост, но я хочу добавить то, что я недавно построил для простых запросов

    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 запросов, попробовать все же стоит.

Кстати: забудьте об именах, это был прототип, ничего более.

0 голосов
/ 23 декабря 2010

Кажется, нет способа уменьшить количество кода. Я полагаю, что ради безопасности типов нужно было пожертвовать чем-то.

...