본문 바로가기
Spring/JPA

@OneToOne 는 1:1 을 보장하지않는다 + unique 제약조건

by YoonJong 2022. 10. 17.
728x90

@OneToOne ( 1:1 ) 매핑을 하면 데이터 입력 시 1:1 을 보장할까??

 

위의 내용에 대해 테스트를 해보았다.

 

Member 클래스, Locker 클래스가 있다.

조건은 Member 1명당 1개의 Locker만 사용할 수 있다.

Member 클래스가 연관관계의 주인이 되며, Locker 클래스에서는 mappedBy를 사용해 양방향으로 연결해준다.

 

테스트 내용 : 1명의 락커에 1명 이상의 멤버가 들어가는지 확인한다.

public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String username;

    @OneToOne
    @JoinColumn(name = "locker_id")
    private Locker locker;
}
public class Locker {

    @Id @GeneratedValue
    @Column(name = "locker_id")
    private Long id;
    private String name;

    @OneToOne(mappedBy = "locker")
    private Member member;
}

 

락커 1개를 생성해주었으며, 멤버는 2명을 생성해주었다.

멤버 1과 2에 모두 동일한 락커를 세팅해주고 실행해보았다.

Locker locker = new Locker(); // 락커 1개 생성
locker.setName("Locker1");
em.persist(locker);


Member member = new Member(); // member1 생성
member.setUsername("member1");
member.setLocker(locker); // 라커 1 지정
em.persist(member);

Member member2 = new Member(); // member2 생성
member2.setUsername("member2"); 
member2.setLocker(locker); // 라커 1 지정
em.persist(member2);

결과를 확인해보면 @OneToOne 관계임에도 불구하고 1:1 매핑이 이루어지지 않았다.

 

@OneToOne은 < @OneToOne ( 1:1 ) 매핑을 하면 데이터 입력 시 1:1 을 보장할까? >

라는 조건이 틀리다 라는 것을 알 수 있다.

 

그러면 1:1 로 매핑 ( member1 - locker1 가능 / member2 - locker1 실패 ) 하기 위해서는 어떻게 해야할까?

 

바로 Member 테이블의 locker 에 unique 제약조건을 추가해 조건을 만족시킬 수 있다.

public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String username;

    @OneToOne
    // unique 제약조건 추가
    @JoinColumn(name = "locker_id", unique = true)
    private Locker locker;
}

테스트를 해보자

콘솔에 unique 로 인해 에러가 발생한것을 확인할 수 있으며, DB 에서도 추가되지 않은 것을 확인할 수 있다.

728x90

댓글