일대일 연관관계를 회원(Member)과 해당 회원의 사물함(Locker)을 예시로 설명해보도록 하겠습니다.
일대일 (1:1)
관계는 양쪽이 서로 하나의 관계만 갖습니다.
일대일 관계에는 주 테이블과 대상 테이블이 관계를 맺습니다.
일대일 (1:1)
에서 일대다 (1:N)
으로 변경할 때, 테이블 구조를 그대로 유지할 수 있습니다.위 관계를 통해서 객체 및 테이블 모델링을 한 결과는 아래와 같습니다.
해당 객체 모델링을 코드로 나타내어 보도록 하겠습니다.
Member 클래스 (일대일
에서 주 테이블
에 해당합니다.)
public class Member {
@Id
@Column(name = "MEMBER_ID")
private Long id;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
@Column(name = "USERNAME")
private String username;
// Getter, Setter, Constructor
}
Locker 클래스 (일대일
에서 대상 테이블
에 해당합니다.)
public class Locker {
@Id
@Column(name = "LOCKER_ID")
private Long id;
@Column(name = "NAME")
private String name;
// Getter, Setter, Constructor
}
주 테이블에 외래키를 저장하는 단방향 관계
일 경우, 주 테이블
에 해당하는 클래스에 대상 테이블
에 해당하는 클래스를 참조 필드로 작성해주시면 됩니다.
이때, 해당 참조 필드위에 OneToOne
과 @JoinColumn(name = "외래키 이름")
을 추가하여 줍니다.
외래키를 매핑할 때 사용합니다.
자세한 속성은 JPA 단방향 연관관계 에 있는 설명과 동일합니다.
JoinColumn 어노테이션은 생략 가능합니다.
@JoinColumn을 생략하면 외래 키를 찾을 때 기본 전략을 사용합니다.
기본 전략 : 필드명 + _ + 참조하는 테이블의 컬럼명
일대일 관계에서 사용합니다.
속성 | 기능 | 기본값 |
---|---|---|
optional | false로 설정하면 연관된 엔티티가 항상 있어야 한다 | true |
mappedBy | 연관관계의 주인 필드를 선택한다. 양방향 매핑시 사용됩니다. | |
fetch | 글로벌 패치 전략을 설정한다. (자세한 내용은 추후에) | @OneToOne=FetchType.EAGER (즉시 로딩) |
cascade | 영속성 전이 기능을 사용한다. (자세한 내용은 추후에) | |
orphanRemoval | true 로 설정 시, 고아 객체를 즉시 삭제합니다. | false (고아 객체를 삭제하지 않습니다.) |
targetEntity | 연관된 엔티티의 타입 정보를 설정한다. 이 기능은 거의 사용하지 않음 |
연관관계를 등록, 수정, 삭제, 조회하는 예제를 통해 연관관계를 어떻게 사용하는지 알아보겠습니다.
// 사물함 저장
Locker locker = new Locker(0L, "사물함");
entityManager.persist(locker);
// 회원 저장
Member member = new Member(0L, "회원");
member.setLocker(locker); // 연관관계 설정
entityManager.persist(member);
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태이어야 합니다.
위 코드를 실행하였을 때, 실행되는 SQL 은 아래와 같습니다.
INSERT INTO LOCKER (LOCKER_ID, NAME) VALUES (0, "사물함");
INSERT INTO MEMBER (MEMBER_ID, USERNAME, LOCKER_ID) VALUES (0, "회원", 0);
연관관계가 있는 엔티티를 조회하는 방법은 크게 2가지가 있습니다.
객체그래프 탐색
member.getLocker() 을 사용해서 member 와 연관된 locker 엔티티를 조회할 수 있습니다.
Member member = entityManager.find(Member.class, 0L);
Locker locker = member.getLocker();
객체지향 쿼리 (JPQL) 사용
String jpql = "select m.locker from Member m where m.id = :memberId";
Locker locker = entityManager
.createQuery(jpql, Locker.class)
.setParameter("memberId", 0L)
.getSingleResult();
SELECT l.LOCKER_ID, l.NAME
FROM LOCKER l
JOIN MEMBER m ON l.LOCKER_ID = m.LOCKER_ID
WHERE m.MEMBER_ID = 0;
회원이 소유하고 있던 사물함을 신규 사물함으로 변경해보도록 하겠습니다.
Locker locker = new Locker(1L, "신규 사물함");
entityManager.persist(locker);
Member member = entityManager.find(Member.class, 0L);
member.setLocker(locker);
UPDATE MEMBER
SET LOCKER_ID = 1, ...
WHERE
MEMBER_ID = 0;
회원의 사물함 기간이 종료되어, 소유하고 있던 사물함과의 연관관계를 제거해보도록 하겠습니다.
Member member = entityManager.find(Member.class, 0L);
member.setLocker(null);
UPDATE MEMBER
SET LOCKER_ID = null, ...
WHERE
MEMBER_ID = 0;
회원이 서비스를 탈퇴하여 회원 객체를 삭제해보도록 하겠습니다.
Member member = entityManager.find(Member.class, 0L);
entityManager.remove(member);
DELETE
FROM MEMBER
WHERE MEMBER_ID = 0;
orphanRemoval 을 true 로 설정 시, 회원 객체를 삭제할 때 고아 객체가 되는 사물함 객체 역시 삭제가 됩니다.
위 관계를 통해서 객체 및 테이블 모델링을 한 결과는 아래와 같습니다.
해당 객체 모델링을 코드로 나타내어 보도록 하겠습니다.
Member 클래스 (일대일
에서 주 테이블
에 해당합니다.)
public class Member {
@Id
@Column(name = "MEMBER_ID")
private Long id;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
@Column(name = "USERNAME")
private String username;
// 순수한 객체를 고려한 연관관계 편의 메서드
public void setLocker(Locker locker) {
if (this.locker != null) {
this.locker.setMember(null);
}
this.locker = locker;
if (locker != null) {
locker.setMember(this);
}
}
// Getter, Setter, Constructor
}
Locker 클래스 (일대일
에서 대상 테이블
에 해당합니다.)
public class Locker {
@Id
@Column(name = "LOCKER_ID")
private Long id;
@Column(name = "NAME")
private String name;
@OneToOne(mappedBy = "locker")
private Member member;
// Getter, Setter, Constructor
}
주 테이블에 외래키를 저장하는 양방향 관계
일 경우, 주 테이블
에 해당하는 클래스는 주 테이블에 외래키를 저장하는 단방향 관계
와 동일합니다.
대상 테이블
에 해당하는 클래스에 주 테이블
에 해당하는 클래스를 참조 필드로 작성해주시면 됩니다.
이때 해당 필드위에 @OneToOne(mappedBy = "반대쪽 매핑의 필드 이름값")
을 추가하여 줍니다.
연관관계를 등록, 수정, 삭제, 조회하는 예제를 통해 연관관계를 어떻게 사용하는지 알아보겠습니다.
// 사물함 저장
Locker locker = new Locker(0L, "사물함");
entityManager.persist(locker);
// 회원 저장
Member member = new Member(0L, "회원");
member.setLocker(locker); // 연관관계 설정
entityManager.persist(member);
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태이어야 합니다.
위 코드를 실행하였을 때, 실행되는 SQL 은 아래와 같습니다.
INSERT INTO LOCKER (LOCKER_ID, NAME) VALUES (0, "사물함");
INSERT INTO MEMBER (MEMBER_ID, USERNAME, LOCKER_ID) VALUES (0, "회원", 0);
객체그래프 탐색
member.getLocker() 을 사용해서 member 와 연관된 locker 엔티티를 조회할 수 있습니다.
Member member = entityManager.find(Member.class, 0L);
Locker locker = member.getLocker();
객체지향 쿼리 (JPQL) 사용
String jpql = "select m.locker from Member m where m.id = :memberId";
Locker locker = entityManager
.createQuery(jpql, Locker.class)
.setParameter("memberId", 0L)
.getSingleResult();
SELECT l.LOCKER_ID, l.NAME
FROM LOCKER l
JOIN MEMBER m ON l.LOCKER_ID = m.LOCKER_ID
WHERE m.MEMBER_ID = 0;
객체그래프 탐색
locker.getMember() 을 사용해서 locker 를 소유하고 있는 엔티티를 조회할 수 있습니다.
Locker locker = entityManager.find(Locker.class, 0L);
Member member = locker.getMember();
객체지향 쿼리 (JPQL) 사용
String jpql = "select l.member from Locker l where l.id = :lockerId";
Member member = entityManager
.createQuery(jpql, Member.class)
.setParameter("lockerId", 0L)
.getSingleResult();
SELECT m.MEMBER_ID, m.LOCKER_ID, m.USERNAME
FROM Member m
JOIN Locker l ON m.LOCKER_ID = l.LOCKER_ID
WHERE l.LOCKER_ID = 0;
회원이 소유하고 있던 사물함을 신규 사물함으로 변경해보도록 하겠습니다.
Locker locker = new Locker(1L, "신규 사물함");
entityManager.persist(locker);
Member member = entityManager.find(Member.class, 0L);
member.setLocker(locker);
UPDATE MEMBER
SET LOCKER_ID = 1, ...
WHERE
MEMBER_ID = 0;
회원의 사물함 기간이 종료되어, 소유하고 있던 사물함과의 연관관계를 제거해보도록 하겠습니다.
Member member = entityManager.find(Member.class, 0L);
member.setLocker(null);
UPDATE MEMBER
SET LOCKER_ID = null, ...
WHERE
MEMBER_ID = 0;
회원이 서비스를 탈퇴하여 회원 객체를 삭제해보도록 하겠습니다.
Member member = entityManager.find(Member.class, 0L);
entityManager.remove(member);
DELETE
FROM MEMBER
WHERE MEMBER_ID = 0;
다음 포스트에서는 일대일 연관관계 시, 대상 테이블에 외래키를 저장하는 형태에 대해서 알아보도록 하겠습니다.
Escorts Lajpat Nagar is all about premium companionship for those who appreciate class and beauty. With an impressive range of companions to choose from, you get the opportunity to find someone who suits your mood and style. Each interaction is designed to make you feel valued, relaxed, and happy. If you’re seeking an elite and confidential experience in Lajpat Nagar, this service will definitely provide exactly what you desire.