jpa dirty checking is not working
말그대로 JPA 에서 더티 체킹이 되지 않는다. 물론 더티체킹 사용하는걸 좋아하진 않지만 왜 안되는건지 알고싶다.
코드로 보는게 편할듯하여 코드부터 살짝 본다면 문제의 엔티티는 다음과 같다.
@Entity
@Table(name = "company", catalog = "slave_babi_01")
data class SlaveCompany(
...
@Column(name = "name")
private var name: String = ""
){
fun changeName(name: String){
this.name = name
}
}
그리고 그 문제의 서비스 코드는 다음과 같다.
@Service
@Transactional
class CompanyService(
private val masterCompanyRepository: MasterCompanyRepository,
private val slaveCompanyRepository: SlaveCompanyRepository
) {
...
fun changeSlaveCompanyName(id: Long, name: String){
val company = slaveCompanyRepository.findById(id)
.orElseThrow()
company.changeName(name)
}
}
그럼 이 문제의 코드를 실행해보자
@Test
fun change_slave_name_test(){
// given
val id = 1L
val changeName = "change slave name"
// when
companyService.changeSlaveCompanyName(id,changeName)
// then
val slaveCompany = slaveCompanyRepository.findById(id)
.orElseThrow()
assertThat(slaveCompany.name).isEqualTo(changeName)
}
이녀석 진짜 문제네
그러게 말이다. 한번 이것저것 시도를 해봤었다.
fun changeSlaveCompanyName(id: Long, name: String){
val company = slaveCompanyRepository.findById(id)
.orElseThrow()
company.changeName(name)
// 직접 save 추가
slaveCompanyRepository.save(company)
}
예 됩니다. update 쿼리 잘날라가네요
@Service
@Transactional
class CompanyService(
private val masterCompanyRepository: MasterCompanyRepository,
private val slaveCompanyRepository: SlaveCompanyRepository,
// EntityManager 추가
private val entityManager: EntityManager
) {
...
fun changeSlaveCompanyName(id: Long, name: String){
val company = slaveCompanyRepository.findById(id)
.orElseThrow()
// 추가
entityManager.contains(company)
company.changeName(name)
}
}
안되어 있었네요.
혼날까봐 미리 이야기안했었는데, 사내 프로젝트에서 다중 datasource 를 만들어서 사용하고 있었고, slaveDatasource
, masterDatasource
를 각각 선언해서 사용중이다.
그리고 config 파일을 찾아보니 다음과 같이 설정되어 있었다.
그리고 당연하게 @Primary
붙은 masterDatasource
를 기본으로 사용하게되어 내가 원하는 Slave
관련 entity 는 관리 대상이 아니어서 더티체킹이 나가지 않았던것...
아오 @Primary
그래서 트랜잭션에 직접 내가 사용할 Transaction Manager
를 기재해주면 더티체킹을 사용할수있다~
// 내가 사용할 transactionManager 명시
@Transactional(transactionManager = "slaveTransactionManager")
fun changeSlaveCompanyName(id: Long, name: String){
val company = slaveCompanyRepository.findById(id)
.orElseThrow()
company.changeName(name)
}
update도 기똥차게 나가는걸 확인할수있다