Что такое хороший дизайн для запроса “layer” для Java JPA

StackOverflow https://stackoverflow.com/questions/177927

  •  05-07-2019
  •  | 
  •  

Вопрос

В 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" (в основном это следствие отсутствия замыканий или "with statement" или чего-то подобного в Java).

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

@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("непроверенный") не нужен, но он избавляет от предупреждения, неизбежного в противном случае, при приведении результата не общего списка из getResultList() к общему списку;и

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

Он достаточно лаконичен и полон.

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

На самом деле я использую Seam.И предложение объекта запроса привело меня к поиску спящих режимов Запросы по критериям (Запрос на примере) функциональность.Это кажется очень близким к тому, что я искал.

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

Моин!

Вот моя версия для отдельных результатов (я использую ее в своих настольных приложениях JPA с TopLink essentials):

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));

с наилучшими пожеланиями, джош.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top