Использование транзакций в DAO

Я использую Hibernate 3.6.9 с Atomikos и Spring 3.1. После прочтения Куда относится аннотация @Transactional? я удалил аннотации @Transactional из все DAO, и я оставил их только на сервисе. После удаления этих аннотаций в любой операции dao db я получаю

org.hibernate.HibernateException: Unable to locate current JTA transaction

Моя конфигурация:

    <tx:annotation-driven transaction-manager="jtaTransactionManager" />


    <!-- Configure the Spring framework to use JTA transactions from Atomikos -->
    <bean id="jtaTransactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="atomikosTransactionManager" />
        <property name="userTransaction" ref="atomikosUserTransaction" />
    </bean>

    <!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
        init-method="init" destroy-method="close">

        <!-- when close is called, should we force transactions to terminate or 
            not? -->
        <property name="forceShutdown" value="false" />
    </bean>

    <!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">

        <property name="transactionTimeout" value="300" />
    </bean>

Свойства фабрики сеансов:

                <prop key="hibernate.connection.isolation">3</prop>
                <prop key="hibernate.current_session_context_class">jta</prop>
                <prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
                </prop>
                <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
                </prop>

Как мне управлять транзакциями DAO и как я могу использовать DAO вне Сервиса? Единственный способ решить эту проблему — запускать транзакции вручную (транзакционные с распространением require_new) на любом уровне, использующем daos? Однако при использовании Transactional с DAO я столкнулся с проблемами отложенных исключений инициализации (транзакция закрывается до уровня представления - пытается инициализировать поля сущности).

Редактировать:

Как мне управлять транзакциями, когда контроллер Spring MVC может напрямую обращаться к DAO? Должен ли контроллер быть транзакционным?

Моя проблема также возникает во время процесса входа в систему, потому что Spring Security использует dao (без @Transactional), поэтому ни один уровень не запускает транзакцию?

Добавление @Transactional, например. daos, используемый Spring Security, решает проблему -> когда есть @Transactional, все работает, но невозможно использовать db без этих аннотаций. Но добавление @Transactional к некоторым DAO вызывает проблемы, потому что, когда spring mvc хочет отобразить некоторые данные, появляется исключение ленивой инициализации, а затем работает только ручной Hibernate.initialize в dao (поскольку последний @Transactional закрывает транзакцию перед уровнем представления!).


person mmatloka    schedule 31.12.2011    source источник
comment
Я предполагаю, что проблема в том, что аннотация @Transaction к вашим услугам не принимается во внимание. -- Опубликуйте один из методов службы с аннотацией транзакции, а также метод со статусом, который вызывает метод, и часть конфигурации, которая включает поддержку аннотации транзакции.   -  person Ralph    schedule 31.12.2011
comment
@Ralph Я расширил свой вопрос.   -  person mmatloka    schedule 31.12.2011


Ответы (2)


ИМО, вы должны инициализировать те поля объектов в DAO, которые позже потребуются на уровне представления.

Если нетерпеливая инициализация этих объектов кажется вам несколько «грязной», вы должны ввести новые классы, специфичные для уровня представления (модель представления), которые отображаются на вашем сервисном уровне (у которого все еще есть открытая транзакция для чтения, если это необходимо).

Поскольку у меня нет фона Java, я не знаю, нужен ли «весенней безопасности» доступ к базе данных. Если это так, вы должны добавить эти транзакционные атрибуты и на соответствующий сервисный уровень, как вы уже выяснили. Однако я не думаю, что вы обязательно должны помещать транзакционные атрибуты в методы DAO, которые часто находятся на одном уровне глубже.

person tobsen    schedule 31.12.2011
comment
Разрешение исключения lazili initialize путем инициализации этих полей в dao имеет еще один недостаток — мы все еще работаем с отсоединенными объектами. Я рассматриваю возможность расширения области сеанса до уровня представления с помощью OpenSessionInViewFilter. - person mmatloka; 31.12.2011
comment
вам не следует пытаться поймать исключение, но убедитесь, что объекты, переданные обратно с вашего сервисного уровня на уровень представления, содержат все необходимые - и, следовательно, инициализированные - значения. - person tobsen; 31.12.2011

Нет, ошибка говорит вам настроить менеджер транзакций JTA:

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/transaction/jta/JtaTransactionManager.html

Выберите тот, который лучше всего подходит для вашей ситуации.

Этот вопрос форума Hibernate также может быть уместным:

https://forum.hibernate.org/viewtopic.php?p=2430788

Контроллеры не должны быть транзакционными. Вы нашли их в нужном месте — они принадлежат службам.

OpenSessionInView может быть вашим решением:

http://springtips.blogspot.com/2007/07/open-session-in-view.html

А может и нет:

Почему Hibernate Open Session in View считается плохим практика?

person duffymo    schedule 31.12.2011
comment
Я настроил менеджер транзакций JTA так, как это описано в документации по атомикосу. - person mmatloka; 31.12.2011
comment
Соответствует ли подпись класса Spring JTA? Если нет, то как он будет использоваться? Извините, я не знаком с Атомикосом. Проверьте этот вопрос на форуме Hibernate. Он говорил о проблемах с сессией. - person duffymo; 31.12.2011