작성
·
294
0
안녕하세요,
Spring없이 JPA를 적용하여 데스크탑 애플리케이션을 만들어 보던 중,
궁금한 점이 생겨 질문드립니다.
// AbstractDao
public void transaction(EntityManagerRunable runnable) {
EntityManager em = createEntityManager();
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
runnable.run(em);
transaction.commit();
} catch (Throwable e) {
if (transaction.isActive()) {
transaction.rollback();
}
throw new RuntimeException(e);
} finally {
em.clear();
em.close();
}
}
// MemberDao
public Member findByName(String name) {
return transaction((em) -> {
return em.createQuery("select r from Member m where m.name = :name", Member.class)
.setParameter("name", name)
.getSingleResult();
}
// MemberDao
public void updateTeam(String name, String team) {
transaction((em) -> {
Member findMember = findByName(name);
findMember.changeTeam(team);
});
}
위와 같이 AbstractDao와 MemberDao의 메서드가 구성되어 있는 상태에서
MemberDao에서 updateTeam 메서드를 호출하면 변경감지가 되지 않아, 업데이트 쿼리가 나가지 않습니다.
안쪽의 트랜잭션 (findByName의 트랜잭션)이 종료되고, findMember 객체는 바깥쪽 트랜잭션 안에서 영속 상태가 아니기 때문에 team 필드 변경에도, 변경감지가 되지 않는 것 같다고 판단이 됩니다.
그러면, Spring의 propagation옵션 같이 중첩된 트랜잭션들을 한 개의 트랜잭션처럼 동작하도록 구성할 수 있을까요?
조언 부탁드립니다.
답변 1
0
안녕하세요. melo님
코드로 트랜잭션을 전파하는 방식으로 구현하는 것은 매우 어렵습니다. 이전 트랜잭션 정보를 찾아야 하는데 이 부분이 까다롭습니다. 그런데 크게 고민하지 않아도 되는 이유는 실무에서는 보통 스프링과 JPA를 함께 사용하기 때문에 스프링의 @Transactional을 사용해서 JPA 트랜잭션도 자연스럽게 전파할 수 있습니다.
관련해서 활용1편에서 이런 방식으로 처리합니다.
감사합니다.