
TransactionalEventListener 가 동작을안한다!!!그러니깐 내가 원하는대로 동작을 하지않는다. 이벤트 리스너에서 데이터 변경이 반영되지 않는다...
간단한 코드를 보겠다.
GroupService.kt 에서 Group 을 삭제하고 삭제 이벤트를 발행한다. /**
* GroupService.kt
*/
@Transactional
fun deleteGroupPublish(id: Long){
groupRepository.deleteById(id)
applicationEventPublisher.publishEvent(
DeleteGroupEvent(id)
)
}
Group 에 속하는 GroupMember 를 삭제한다. /**
* GroupMemberService.kt
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
fun deleteGroupMemberEventHandler(event: DeleteGroupEvent){
groupMemberRepository.deleteByGroupId(event.id)
}
@SpringBootTest
class GroupServiceTest{
@Autowired
lateinit var groupService: GroupService
@Autowired
lateinit var groupRepository: GroupRepository
@Autowired
lateinit var groupMemberRepository: GroupMemberRepository
@Test
fun delete_group_and_publish_event(){
// given
val group = groupRepository.save(Group())
val groupMember = groupMemberRepository.save(GroupMember(group.no))
// when
groupService.deleteGroup(group.no)
// then
val groupList = groupRepository.findAll()
val groupMemberList = groupMemberRepository.findAll()
assertThat(groupList).isEmpty()
assertThat(groupMemberList).isEmpty()
}
}

그러니깐 ORM 에 등록해서 데이터베이스가 실제로 변경되게 하려면commit,rollback등의 기능이 되어야하고, 그걸 편하게 하기위해서TransactionManager인터페이스가 존재하고, 이걸 대부분 구현해놓은AbstractPlatformTransactionManager추상클래스가 존재하고, 이걸 또 각자 사용하는 ORM에서TransactionManager를 구현해놓았는데...
나중에 블로그를 따로 정리하겠다.
구글링으로 좀 이것저것 찾아봤었는데 여기 블로그를 좀 참고했다.
일단 내부구조를 슥 한번 보겠다.
변경사항이 반영되는doCommit() 을 실행하는 부분은 여기 한군데 밖에 없다
AbstractPlatformTransactionManager 클래스의 processCommit() 메서드이다.

코드를 보아 status.isNewTransaction() 이 true 여야 doCommit() 이 실행되어 데이터베이스 변경이 반영할수있다는걸 알수 있다.
그렇다면 status.isNewTransactiion() 의 상태값이 세팅 부분을 찾아보겠다.
동일한 클래스의 getTransaction() 에서 현재 실행중인 Transaction 이 새로운 트랜잭션인지 분기한다는걸 확인했다.
현재 Transactional 의 propagation이 기본값 (Propagation.REQUIRED)으로 되어있으니 하단의 조건문에 걸려 트랜잭션을 시작하게 된다.

그리고 해당 메서드는 트랜잭션을 생성하며 newTransaction이 true로 들어가는걸 확인할수 있다.

AbstractPlatformTransactionManager 클래스의 processCommit() 메서드의 status.isNewTransaction()이 true 로 들어갈수가 있겠다.
(중복된 사진)

동일하게 getTransaction()으로 현재 트랜잭션의 상태값을 받아오는건 동일하지만, 상위 클래스에서 전파된 트랜잭션이 존재하기 때문에 handleExistingTransaction() 메서드를 타게 된다.

그리고 handleExistingTransaction 내부를 확인하면 definition.getPropagationBehavior() 에 따라서 트랜잭션의 newTransaction 의 상태값이 다르게 들어가는걸 확인할수 있다.
그리고 해당 값의 기본값은 Transactional의 기본값인 REQUIRED

PROPAGATION_REQUIRED 상태값을 따라가면 마지막에 newTransaction 이 false 로 생성되게 되고 아까 확인했었던 commit이 일어나지 않게 된다.

상위클래스에서 전파된 트랜잭션은뭐 그거대로 두고 새로운 트랜잭션을 열면 된다.
아까 확인했었던 handleExistingTransaction 에서 트랜잭션 PROPAGATION이 REQUIRES_NEW 라면 최초에 트랜잭션을 열때와 동일하게 여는 방식을 사용하는걸 볼수 있다.

그렇지만 여기 블로그 도 한번 확인해보도록 하자.