【发布时间】:2012-06-25 18:45:07
【问题描述】:
我知道我们需要使@Transactional 边界尽可能短。这是代码:
我正在通过 Spring 依赖注入使用 userDAO 对象:
private static ApplicationContext context ;
private UserDAO userDAO;
public TransactionsTest() {
userDAO = (UserDAO) context.getBean("userDAO");
}
我从TransactionsTest 类调用testSaveUserAccounts(),试图使用userDAO 插入/更新数据。
案例一:
@Transactional
public void testSaveUserAccounts() {
UserAccounts userAccounts = new UserAccounts();
userAccounts.setCommunityId(10L);
userDAO.saveObject(userAccounts);
}
// This method is inside UserDAO
public void saveObject(Object object) {
entityManager.merge(object);
}
案例 2:
@Transactional
public void testSaveUserAccounts() {
UserAccounts userAccounts = new UserAccounts();
userAccounts.setCommunityId(10L);
userDAO.saveObject(userAccounts);
}
// This method is inside UserDAO
@Transactional(propagation=Propagation.REQUIRED)
public void saveObject(Object object) {
entityManager.merge(object);
}
弹簧上下文:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceLocal" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceUnitName" value="spring-jpa" />
</bean>
用户DAO:
@Repository
public class UserDAO extends BaseDAO {
@Transactional(propagation=Propagation.REQUIRED)
public void saveObject(Object object) {
entityManager.merge(object);
}
}
BaseDAO:
public abstract class BaseDAO {
protected EntityManager entityManager;
protected HashMap<String,Long> eventIdMap = new HashMap<String,Long>();
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
public <T> T getById(final Class<T> clazz, final Serializable id) {
T object = clazz.cast(entityManager.find(clazz, id));
return object;
}
@Transactional
public Object save(Object ob) {
Object object = entityManager.merge(ob);
return object;
}
@Transactional
public void persist(Object ob) {
entityManager.persist(ob);
}
@SuppressWarnings("unchecked")
public <T> ArrayList<T> getAll(final Class<T> clazz) {
String hqlQuery = "from "+ clazz.getSimpleName();
ArrayList<T> list = (ArrayList<T>)entityManager.createQuery(hqlQuery).getResultList();
return list;
}
}
我一直在围绕几个事务边界进行试验 REQUIRED、REQUIRES_NEW、SUPPORTS 等,但无法确定为什么案例 1(当调用方法 2 时,它在方法 1 的事务边界内)确实如此不合并数据,而在案例 2 中解决了这个问题。
既然我已经在事务边界内标记了调用函数,为什么还要在内部方法中指定@Transactional?
【问题讨论】:
-
你没有,它应该可以正常工作。其他问题/不同,也许 method1 不在实际应用 AOP 拦截器的地方?
-
如果我们在内部方法中插入/更新数据(没有事务边界),它不会提交我的更改,即使在方法 1 完成后也是如此。这可以通过将 @Transactional 放在内部方法定义上来解决。
-
我认为您需要添加一些真实的代码,您的示例非常简化,您的问题甚至不再存在。
-
@RasmusFranke 如果有帮助,请查看上面的编辑问题摘要。
-
testSaveUserAccounts() 真的在 Spring bean 中吗?如果忽略该方法上的
@Transactional,您的问题将是有意义的。我看到@Affe 也暗示了这一点。
标签: java spring transactions