Декларативные весенние транзакции не совершаются

У меня есть следующие классы обслуживания:

public class UserLoginServiceImpl implements UserLoginService {

  private UserDAO dao;

  public UserLoginServiceImpl(UserDAO dao) {this.dao = dao; }

  public User login(String userName, String password) {
     User u = dao.findUserByCredentials(userName, password);
     if (u == null) {
         throw new UserNotFoundException();
     }
     return u;
}

public class UserManagementServiceImpl implements UserManagementService {

  private UserDAO dao;

  public UserManagementServiceImpl(UserDAO dao) { this.dao = dao; }

  public void createUser(User u) {
     dao.save(u);
  }
}

Мои сервисные интерфейсы находятся в пакете com.mysystem.services, а мои реализации сервисов — в пакете com.mysystem.services.impl.

Я использую спящий режим в качестве реализации jpa и декларативных транзакций весной. Мой файл конфигурации выглядит следующим образом:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="serviceMethod" expression="execution(* com.mysystem.services.impl.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config>

<!--
    Beans
 -->
<bean id="userDao" class="com.mysystem.dao.UserDAOImpl">
    <constructor-arg ref="entityManagerFactory" />
</bean>

<bean id="userLoginService" class="com.mysystem.services.impl.UserLoginServiceImpl">
    <constructor-arg ref="userDao" />
</bean>
<bean id="userManagementService" class="com.mysystem.services.impl.UserManagementServiceImpl">
    <constructor-arg ref="userDao" />
</bean>

Наконец, где-то в моем коде я запускаю следующее:

UserManagementService userManagementService = context.getBean(UserManagementService.class);
userManagementService.createUser(new User("test", "test"));

UserLoginService userLogginService = context.getBean(UserLoginService.class);
User user = userLogginService.login("test", "test");

что приводит к тому, что метод login() выдает исключение UserNotFoundException, поскольку он не может найти пользователя, вставленного ранее с помощью createUser(), что означает, что режим гибернации не будет очистить сеанс между вызовами методов. Я могу проверить эту форму вывода консоли (я вижу операторы create и select в hibernate, но не insert).

Почему транзакция не фиксируется вскоре после вызова createUser()? Что я здесь делаю неправильно?

РЕДАКТИРОВАТЬ:

Использование аннотации @Transactional вместо декларативных транзакций работает. Однако использование @Transactional для меня не вариант. Мне нужно реализовать декларативные транзакции.

Ниже приведен отладочный вывод весны:

13:03:18,174 DEBUG [main] jpa.JpaTransactionManager     - Creating new transaction with name [com.mysystem.services.impl.UserManagementServiceImpl.createUser]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
13:03:18,175 DEBUG [main] jpa.JpaTransactionManager     - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@1af6a711] for JPA transaction
Hibernate: 
    select
        nextval ('hibernate_sequence')
13:03:18,255 DEBUG [main] jpa.JpaTransactionManager     - Initiating transaction commit
13:03:18,255 DEBUG [main] jpa.JpaTransactionManager     - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1af6a711]
13:03:18,256 DEBUG [main] jpa.JpaTransactionManager     - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@1af6a711] after transaction

    13:03:18,263 DEBUG [main] jpa.JpaTransactionManager     - Creating new transaction with name [com.mysystem.services.impl.UserLoginServiceImpl.login]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
    13:03:18,263 DEBUG [main] jpa.JpaTransactionManager     - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@1533badd] for JPA transaction
    Hibernate: 
        /* 
    from
        com.mysystem.domain.User u 
    where
        u.userName = :userName 
        and u.password = :password */ select
            user0_.id as id0_,
            user0_.password as password0_,
            user0_.userName as userName0_ 
        from
            Users user0_ 
        where
            user0_.userName=? 
            and user0_.password=? limit ?
    13:03:18,374 TRACE [main] sql.BasicBinder     - binding parameter [1] as [VARCHAR] - test
    13:03:18,374 TRACE [main] sql.BasicBinder     - binding parameter [2] as [VARCHAR] - test
    13:03:18,379 DEBUG [main] jpa.JpaTransactionManager     - Initiating transaction commit
    13:03:18,379 DEBUG [main] jpa.JpaTransactionManager     - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1533badd]
    13:03:18,379 DEBUG [main] jpa.JpaTransactionManager     - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@1533badd] after transaction

person Lefteris Laskaridis    schedule 09.04.2012    source источник
comment
Вы можете выполнить сброс (EntityManager.flush()). Если вы сделаете это после вызова create в сервисном методе, тогда пользователь будет виден для получения метода без фактического совершения транзакции.   -  person Prasanna Talakanti    schedule 09.04.2012


Ответы (1)


Можете ли вы попробовать этот.

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>

        <tx:method name="createUser" propagation="REQUIRES_NEW" />
    </tx:attributes>
</tx:advice>
person erimerturk    schedule 09.04.2012
comment
вам нужна новая транзакция. и это даст вам то, что вам нужно propagation=REQUIRES_NEW. Можете ли вы попробовать и оставить отзыв. - person erimerturk; 09.04.2012
comment
Нет... тоже не получилось. Самое смешное, что это РАБОТАЕТ, когда вместо этого я использую аннотацию @Transactional. Я предполагаю, что это должно быть что-то в моей конфигурации, но я не могу понять это на данный момент. - person Lefteris Laskaridis; 09.04.2012
comment
хм.. хорошо.. вы можете обновить свое выражение pointcut com.mysystem.services.impl.*.*(..) Я думаю, проблема в этом. - person erimerturk; 09.04.2012
comment
вопрос: должен ли я определять свои транзакции в методах класса реализации или интерфейсе? - person Lefteris Laskaridis; 09.04.2012
comment
вы должны определить для реализации. все кажется в порядке. я не мог понять. - person erimerturk; 09.04.2012
comment
Мне удалось решить проблему (наконец-то). В моем дизайне я решил внедрить EntityManagerFactory с помощью внедрения конструктора. Затем я использовал emf в конструкторе моего дао, чтобы создать EntityManager и установить его в качестве переменной-члена экземпляра дао. Мне удалось заставить это работать, когда я изменил свою стратегию внедрения, чтобы использовать аннотацию @PersistenceContext. Я до сих пор не уверен, почему моя первоначальная стратегия не сработала, но конечным результатом является то, что она работает. Мне было бы интересно, если бы кто-нибудь объяснил это. - person Lefteris Laskaridis; 10.04.2012