더티 체킹이 안돼요

김민창·2024년 9월 1일
1

trouble shooting

목록 보기
10/11
post-thumbnail
post-custom-banner

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)
}

이녀석 진짜 문제네


아니 왜죠

그러게 말이다. 한번 이것저것 시도를 해봤었다.

save() 를 직접해주면 되는가?

fun changeSlaveCompanyName(id: Long, name: String){
    val company = slaveCompanyRepository.findById(id)
            .orElseThrow()
    company.changeName(name)
    // 직접 save 추가
    slaveCompanyRepository.save(company)
}

예 됩니다. update 쿼리 잘날라가네요

혹시 EntityManager에 등록되어있을까요


@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 였습니다~

혼날까봐 미리 이야기안했었는데, 사내 프로젝트에서 다중 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도 기똥차게 나가는걸 확인할수있다

profile
개발자 팡이
post-custom-banner

0개의 댓글