Что такое хороший дизайн для запроса «слоя» для Java JPA - PullRequest
2 голосов
/ 07 октября 2008

В JPA сущности - это хорошие аннотированные простые Java-объекты. Но я не нашел хорошего способа взаимодействия с ними и базой данных.

В моем текущем приложении мой базовый дизайн всегда должен иметь идентификатор на основе последовательности в качестве первичного ключа, поэтому мне обычно приходится искать объекты по другим свойствам, чем PK.

И для каждой сущности у меня есть EJB без состояния

@Stateless
public class MyEntApiBean implements MyEntApi {


@PersistenceContext(unitName = "xxx") @Inject EntityManager entityManager;

с методами запроса, которые все являются некоторыми вариациями

/**
 * @return A List of all MyEnts that have some property
 * @param someProp some property
 */
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {

    try {
        final Query query = entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp");
        query.setParameter("someProp", someProp);
        return query.getResultList();
    } catch(final NoResultException nre) {
        log.warn("No MyEnts found");
    }
    return new ArrayList<MyEnt>();
}

Итак:

  1. Я действительно ненавижу иметь эти методы в EJB, потому что они, кажется, принадлежат самим сущностям, а локальные интерфейсы EJB раздражают меня до чертиков.

  2. Я ненавижу дублирование, которое у меня есть в каждом методе с «try, createQuery, getResultList, catch, log, return» (в основном это следствие отсутствия замыканий, «с утверждением» или некоторого такого в Java). *

Есть ли у кого-нибудь предложения по улучшению взаимодействия с сущностями и базой данных, которые решают одну или обе мои проблемы?

В настоящее время я думаю о создании некоторых базовых методов с обобщениями и рефлексией, чтобы получить некоторые обобщенные методы запросов для уменьшения дублирования (проблема 2) (позже я опубликую прототип для проверки).

Спасибо, Андерс

Ответы [ 6 ]

4 голосов
/ 07 октября 2008

Попробуйте шов. Объекты запросов выполняют большую часть работы за вас, и их легко расширять. Или вы всегда можете реализовать подобный шаблон.

В общем, Seam делает много полезных вещей, чтобы преодолеть разрыв между JPA и вашим представлением и бизнес уровнями. Вам не нужно использовать JSF для Seam, чтобы быть полезным.

3 голосов
/ 07 октября 2008

Ты излишне многословен. С одной стороны, getResultList () не генерирует исключение, когда строки не возвращаются (по крайней мере, не в Eclipse или Toplink - я не могу представить, чтобы другой поставщик отличался). getSingleResult () делает, getResultList () не делает. Также вы можете использовать шаблон строителя так:

@SuppressWarnings("unchecked")
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {
  return entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp")
    .setParameter("someProp", someProp);
    .getResultList();
}

должно быть достаточно, чтобы вернуть список результатов, если он есть, или пустой список, если его нет. Следует отметить две вещи:

  1. @ SuppressWarnings ("unchecked") не нужен, но он избавляется от неизбежного предупреждения, которое возникает при преобразовании неуниверсального результата List из getResultList () в универсальный List; и

  2. Вероятно, стоит заменить вызов createQuery () на @NamedQuery на MyEnt (обычно). С одной стороны, это позволит проверить время развертывания и другие полезные вещи.

Это достаточно кратко и полно.

1 голос
/ 19 октября 2009

Moin!

Вот моя версия для единичных результатов (я использую ее в настольных JPA-приложениях с базовыми функциями TopLink):

public class JPA {
  @SuppressWarnings ("unchecked")
  public static <T> T querySingle(
      EntityManager em, 
      Class<T> clazz, 
      String namedQuery, 
      Pair... params) 
  {
    Query q = em.createNamedQuery(namedQuery);
    for (Pair pair : params) {
      q.setParameter(pair.key, pair.value);      
    }
    List<T> result = q.getResultList();
    if ( result.size() == 0 ) {
      return null;
    }
    if ( result.size() == 1 ) {
      return result.get(0);
    }
    throw new 
      IllegalStateException(
        "To many result rows for query: " 
         + namedQuery 
         + " where " 
         + Arrays.toString(params));
  }

  public static class Pair {
    String key;
    Object value;

    public static Pair param (String key, Object value) {
      return new Pair (key, value);
    }

    public Pair (String key, Object value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public String toString() {
      return key + "=" + value;
    }
  }
}

И использование:

import static org.sepix.JPA.*;
...

String id = ...
Customer customer = querySingle (em, Customer.class, 
                      "Customer.findByID", Pair.param ("id", id));

или

String inquiryID = ...
Boolean current = Boolean.TRUE;
Inquiry inq = querySingle (em, Inquiry.class, 
                      "Inquiry.findCurrent", 
                      Pair.param ("inquiry", inquiryID),
                      Pair.param ("current", current));

С наилучшими пожеланиями, Нав.

1 голос
/ 07 октября 2008

Я на самом деле использую Seam. И предложение объекта Query побудило меня найти Hibernates Критерии запросов (Query By Example) функциональность . Кажется, это очень близко к тому, что я искал.

Может быть, в базовом классе и с чертой обобщений ....?

1 голос
/ 07 октября 2008

Если вы выполняете много текстовых поисков, возможно, вам следует также рассмотреть некоторые основы индексации, такие как Compass .
Я не знаю, подходит ли оно вашему приложению, но если это так, оно может улучшить как дизайн кода, так и производительность.

0 голосов
/ 04 февраля 2010

Я предпочитаю использовать Spring JpaDaoSupport, который помогает работать с JPA. Хороший пример здесь http://github.com/rafalrusin/jpaqb/blob/master/src/test/java/jpaqb/CarDao.java.

Хорошее разделение логики - иметь класс DAO (объект доступа к данным) и DTO (объект передачи данных). DAO обычно содержит все необходимые запросы, а DTO являются объектами с полями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...