2012-09-10 27 views
1

我有一个使用JPA2/Hibernate和Spring @Transactional的JSF2应用程序。 UI中没有@Transactional语句(支持bean),仅在服务层中。 (我在DAO中使用@Transactional(propagation = Propagation.MANDATORY)来确保每次调用都发生在一个事务中。)它的一切都很好,除了...为什么实体管理器需要清除()? - Spring3 @Transactional,JPA2/Hibernate3

当我打开并更新实体时事务服务方法,有时候检索的实体是旧的。无关紧要的是它在同一个会话中是同一个用户,偶尔JPA的“read”方法返回已经被(应该)已经被替换的陈旧实体。这难倒了我很长一段时间,但事实证明这是由实体管理器中的缓存引起的。 DAO用@Repository注释,所以注入的EntityManager正在被重用。我曾预料当交易完成时,实体经理会自动清除。但事实并非如此。实体管理器通常会返回正确的值,但通常会返回并返回早期事务中的旧事务。

作为一种解决方法,我在DAO读取方法中添加了策略entityManager.clear()语句,但这很丑陋。实体管理员应在每次交易后清除。

有没有人遇到过这个?有没有合适的解决方案?每次交易后,实体经理能否被清除?

非常感谢。

我使用:org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean和org.springframework.orm.jpa.JpaTransactionManager

回答

1

@Transactional注解服务层的存在。使用@Transactional标记的服务方法无论从其中创建多少个DAO调用,都将遵守ACID属性。

这意味着您无需将DAO方法注释为@Transactional。

我正在做类似的事情,这就是我做到这一点,我的数据是一致的。

试试看,看看你是否仍然收到不一致的数据。

+0

我想确保如果直接在现有事务之外调用DAO方法之一,则抛出异常。 DAO绝不能开始交易。我认为这就是@Transactional(propagation = Propagation.MANDATORY)会做的事情。 – John

+0

不应该直接调用DAO。服务层访问DAO层。控制器/端点应该访问服务层。那么为什么要考虑直接调用DAO。服务层将调用DAO。 –

+0

如果仅将@Transactional添加到DAO中,即没有传播= Propagation.MANDATORY,则它的行为方式也是相同的。 –

0

你使用@PersistenceContext注释(上述的EntityManager在DAO)与PersistenceAnnotationBeanPostProcessor豆组合(你没有定义PersistenceAnnotationBeanPostProcessor豆如果你正在使用<context:annotation-config/><context:component-scan/> XML标签)?如果没有,我猜这是你问题的原因。

相关问题