inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 DB 2편 - 데이터 접근 활용 기술

외래키 중복 관련 질문

273

작성자 없음

작성한 질문수 0

0

import com.example.banking.domain.user.User
import com.example.banking.support.BaseEntity
import jakarta.persistence.Entity
import jakarta.persistence.FetchType
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne

@Entity
class Account(
    var balance: Double,
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    val user: User,

    id: Long = 0

) : BaseEntity(id) {
    fun addAccount(user: User) {
        user.accounts.add(this)
    }

    fun addBalance(amount: Double) {
        balance += amount
    }
    
    fun subtractBalance(amount: Double) {
        balance -= amount
    }
}
import com.example.banking.domain.account.Account
import com.example.banking.support.BaseEntity
import jakarta.persistence.*

@Entity
class Transaction(
    val amount: Double,
    @Enumerated(EnumType.STRING)
    val type: TransactionType,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    val sender: Account,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    val recipient: Account?,

    id: Long = 0L
) : BaseEntity(id) {
    constructor(amount: Double, type: TransactionType, sender: Account) : this(amount, type, sender, null)
}
import com.example.banking.domain.account.Account
import com.example.banking.domain.user.User
import com.example.banking.domain.user.UserInfo
import com.example.banking.repository.account.AccountRepository
import com.example.banking.repository.transaction.TransactionRepository
import com.example.banking.repository.user.UserRepository
import jakarta.persistence.EntityManager
import jakarta.transaction.Transactional
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.Rollback

@SpringBootTest
@Transactional
@Rollback(value = false)
class TransactionTest(
    @Autowired private val em: EntityManager,
    @Autowired private val transactionRepository: TransactionRepository,
    @Autowired private val userRepository: UserRepository,
    @Autowired private val accountRepository: AccountRepository

) {
    @Test
    fun testTransaction() {
        val user1 = User(UserInfo("b", "Seoul", "123", "123"))
        val user2 = User(UserInfo("b2", "Seoul", "123", "123"))

        userRepository.save(user1)
        userRepository.save(user2)

        em.flush()
        em.clear()

        val account1 = Account(100.0, user1)
        val account2 = Account(100.0, user2)


        account1.addAccount(user1)
        account2.addAccount(user2)

        accountRepository.save(account1)
        accountRepository.save(account2)

        em.flush()
        em.clear()

        val sender = accountRepository.findById(account1.id).get()
        val recipient = accountRepository.findById(account2.id).get()


        val transaction = Transaction(50.0, TransactionType.TRANSFER, sender, recipient)
        transactionRepository.save(transaction)

        em.flush()

        em.clear()


        val transaction2 = Transaction(50.0, TransactionType.DEPOSIT, sender)

        transactionRepository.save(transaction2)


//        assertThat(sender.balance).isEqualTo(50.0)
//        assertThat(recipient.balance).isEqualTo(150.0)

    }
}

 

위와같이 Transaction 엔티티와 Account 엔티티가 ManyToOne 으로 매핑되었을때, 테스트코드를 위와같이 작성시,

transactionRepository.save(transaction2)

이 라인에서 Duplicate entry '97' for key 'transaction.UK_96vb4d846be64bta5qbxiicb1' 에러가 발생합니다.
제가 알기론 외래키의 경우 중복된 값을 가지는것이 가능한것으로 알고 있는데, 같은 account id로 새로운 Transaction 을 생성할 시에 키가 중복이라는 에러가 발생하는데 왜 그런지 알고싶습니다.

 

코틀린으로 코드 작성한 점 양해부탁드립니다..

spring mvc jpa querydsl spring-data-mybatis spring-jpa

답변 1

0

김영한

안녕하세요. co-account님

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

자바를 기반으로 작동하는 코드를 새로 만들어주시겠어요?

그리고 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

 

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

 

추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명

 

링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

RepositoryTest의 패키지 위치가 domain인 이유

0

29

2

REQUIRES_NEW 해결 방법에 대해서 질문있습니다!!

0

29

1

update()에 사용하는 setter 질문드립니다.

0

47

1

SQL 중심적 개발의 문제점에 대한 질문

0

72

1

혹시 Containing 을 안쓰신 이유가 있을까요?

0

83

2

[공유] 스프링부트 4.x 버전 mybatis 연동

0

173

1

@repository 어노테이션

0

89

3

ItemService

0

58

1

논리 커밋, 물리 커밋 질문드립니다.

0

54

1

내부 트랜잭션 커밋은 필수인가요?

0

57

1

프록시 커넥션 객체를 반환할 때 생성하는건가요?

0

54

1

Transaction readOnly 성능 개선 (김영한님의 대한 감사인사)

2

178

2

JPQL 대신 네이티브 쿼리를 사용해야 하는 경우

0

77

1

@EventListener(ApplicationReadyEvent.class) 관련

0

88

1

트랜잭션 동기화 매니저와 데이터 소스

0

76

1

DB 관련 강의 개설 계획은 없으신건가요?

0

133

2

물리 트랜잭션 과 논리트랜잭션 용어를 맞게 이해한걸까요

0

94

1

스프링 3 버전 이상 rollbackFor 변경된듯요

1

112

1

트랜잭션 전파 질문.

0

87

1

프로젝트 오픈 에러

0

126

1

외부 트랜잭션에서 isNewTransaction이 false로 나오는거에 대해 질문드립니다

0

83

2

같은 스레드를 사용하면 트랜잭션 동기화 매니저는 같은 커넥션을 반환

0

72

1

h2 인메모리 테스트중 예약어 충돌날 경우 대처방법

0

102

1

커스텀aop와 트랜잭션을 같이 사용할때 우선순위에 관한 질문

0

98

2