Лучшие практики для транзакций Spring и общих DAO и сервисов

Я работаю над приложением Java EE с помощью Spring и JPA (EclispeLink). Мы разработали удобный интерфейс для администрирования таблиц базы данных. Поскольку теперь я знаю больше о Spring и транзакциях, я решил реорганизовать свой код, чтобы добавить лучшее управление транзакциями. Вопрос в том, как лучше всего работать с универсальными DAO, универсальными сервисами и транзакциями Spring?

Наше текущее решение было:

  • Общий BasicDAO, который имеет дело со всеми распространенными действиями с базой данных (найти, создать, обновить, удалить...)
  • DaoFactory, которая содержит карту реализаций BasicDao для всех типов сущностей (для которых требуются только базовые действия с базой данных) и которая получает entitymanager, внедренный Spring для передачи его в daos.
  • Общий BasicService, который предлагает общие услуги (фактически напрямую связанные с методами dao)
  • ServiceFactory, которая содержит карту реализаций BasicService для всех типов сущностей, которая вводит daoFactory и передает ее службам. У него есть метод "getService(Class T)" для предоставления правильной услуги контроллерам.
  • Контроллеры, соответствующие правильным типам сущностей, делегируют свои запросы универсальному контроллеру, который обрабатывает параметры запроса с помощью отражения и извлекает нужный сервис из карты фабрики сервисов для вызова метода обновления/создания/удаления.

Проблема в том, что когда я добавляю аннотации @Transactionnal к общей службе, а моя фабрика сервисов создает типизированные службы на своей карте, эти службы, похоже, не имеют активных транзакций.

1) Это нормально из-за универсальности и того факта, что только службы, управляемые пружиной, могут иметь транзакции?

2) Какое лучшее решение для решения моей проблемы:

  • Создавать управляемые типизированные службы, реализующие только общую службу, и внедрять их непосредственно в мою фабрику сервисов?
  • Удалить сервисный уровень для этих базовых сервисов? (но, возможно, у меня будет такая же проблема с транзакциями на моем общем уровне дао...)
  • Другие предложения?

Я читал в Интернете некоторые вопросы, связанные с этими пунктами, но не смог найти примеров, которые были бы настолько общими, как здесь, поэтому я надеюсь, что кто-нибудь может мне посоветовать... Заранее спасибо!


person Coralie    schedule 12.06.2013    source источник
comment
вы не можете наследовать аннотации...   -  person NimChimpsky    schedule 12.06.2013
comment
На самом деле речь идет не о наследовании... речь идет о создании экземпляра универсального типа (пример: IService‹T› projectService = new BasicService‹Projet›()// ProjectService не может обрабатывать транзакции, указанные в BasicService, потому что это не управляемый объект ...)   -  person Coralie    schedule 12.06.2013
comment
не создавайте такой экземпляр службы   -  person NimChimpsky    schedule 12.06.2013
comment
У меня есть аналогичная проблема с этим заголовком stackoverflow.com/questions/16774962/   -  person Josef Procházka    schedule 12.06.2013


Ответы (1)


Для базового получения вам не нужен сервисный слой.

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

Моя реализация универсального репозитория выглядит так:

public class DomainRepository<T> {

    @Resource(name = "sessionFactory")
    protected SessionFactory sessionFactory;

 public DomainRepository(Class genericType) {
        this.genericType = genericType;
    }

 @Transactional(readOnly = true)
    public T get(final long id) {
        return (T) sessionFactory.getCurrentSession().get(genericType, id);
    }

@Transactional(readOnly = true)
    public <T> List<T> getFieldEquals(String fieldName, Object value) {
        final Session session = sessionFactory.getCurrentSession();
        final Criteria crit = session.createCriteria(genericType).
                add(Restrictions.eq(fieldName, value));
        return crit.list();
    }
//and so on ..

с разными типами, созданными spring :

<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
        <constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>

и можно ссылаться так:

@Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;

А также может быть расширен вручную для сложных объектов.

person NimChimpsky    schedule 12.06.2013