@Transactionalの境界をできるだけ短くする必要があることを理解しています。コードは次のとおりです。
Springの依存性注入を通じてuserDAOオブジェクトを使用しています:
private static ApplicationContext context ;
private UserDAO userDAO;
public TransactionsTest() {
userDAO = (UserDAO) context.getBean("userDAO");
}
データの挿入/更新にuserDAOを使用しようとしているクラスtestSaveUserAccounts()
から呼び出しています。TransactionsTest
ケース1:
@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>
UserDAO:
@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(メソッド1のトランザクション境界内にあるmethod2が呼び出された場合)がデータをマージしない理由を自信を持って理解できませんでしたが、これはケースで解決されます2.2。
トランザクション境界内で関数の呼び出しをすでにマークしているのに、内部メソッドでも@Transactionalを指定する必要があるのはなぜですか?