[JPA] 연관관계[2/2] - 단방향

2021. 12. 3. 19:54Spring/JPA

단방향 매핑

객체 간의 관계에서는 단방향으로 구현하는 경우가 많다. 지난 시간에 양방향을 알아봤으니 이번에는 단방향을 알아보도록 하자. 양방향을 잘 이해했다면 단방향도 금방 이해할 수 있다.

다대일

다대일 단방향인 경우 한 쪽에서만 연관관계를 가진다. 아래와 같은 경우는 Person이 N, Address는 1인 경우이며 Person에서만 Address를 참조하고 있다. 하지만 이는 DB와는 관계 없다. DB는 여전히 외래 키가 Person에 있는 상태이고 양방향으로 관계를 맺고 있다. 양방향인 경우에서 한 쪽의 참조만 없어진 것이라고 생각하면 된다.

@Entity
class Person {

	@Id
	@GenerateValue
	private Long id;

	@ManyToOne
	@JoinColumn(name = "address_id")
	Address address;
}
@Entity
class Address {

	@Id
	@GenerateValue
	private Long id;

}
create table Person (
	id bigint not null primary key,
	address_id bigint not null
);
create table Address (
	id bigint not null primary key
);

일대다

일대다 단방향인 경우는 아래와 같다.

@Entity
class Person {

	@Id
	@GenerateValue
	private Long id;

	@OneToMnay
	@JoinColumn(name = "address_id")
	Set<Address> addresses = new HashSet<>();
}
@Entity
class Address {

	@Id
	@GenerateValue
	private Long id;

}
create table Person (
	id bigint not null primary key
);
create table Address (
	id bigint not null primary key,
	person_id bigint not null
);

이 경우는 문제가 있다. 엔티티 상에서는 Person이 Address를 관리하고 있는데 실제 외래 키는 Address에 있게 된다. Person의 데이터가 추가된다고 하면 Person 테이블에는 Person 데이터대로 들어가고 Address에도 person_id로 관계가 맺어져 있으므로 추가적인 쿼리가 발생한다. 또한 Address에 데이터를 저장할 때는 Person의 id를 모르기 때문에 또 여기서 추가적인 쿼리가 발생한다. 따라서 매우 비효율적으로 동작한다. 따라서 이러한 매핑은 사용하면 안된다. 이렇게 하는 대신 다대일로 변경하여 사용하는 편이 바람직하다.

다대다

이 경우도 필요로 하지 않는 쪽의 매핑을 제거하면 된다.

@Entity
class Person {

	@Id
	@GeneratedValue
	private Long id;

	@ManyToMany
	@JoinTable(
		name = "person_address",
		joinColumns = @JoinColumn(name = "person_id"),
		inversJoinColumns = @JoinColumn(name = "address_id")
	)
	Set<Address> addresses = new HashSet<>();
}
@Entity
class Address {
	
	@Id
	@GeneratedValue
	private Long id;
}
create table Person (
	id bigint not null primary key
		generated by default as identity,
);
create table Address (
	id bigint not null primary key
);
create table Person_Address (
	person_id bigint not null,
	address_id bigint not null,
	primary key (person_id, address_id)
);

일대일

일대일인 경우도 참조하지 않는 쪽의 매핑을 제거하면 된다.

@Entity
class Person {

	@Id
	@GeneratedValue
	private Long id;

	@OneToOne
	@JoinColumn(name = "person_id")
	private Address address;
}
@Entity
class Address {

	@Id
	@GeneratedValue
	private Long id;

}
create table Person (
	id bigint not null primary key
		generated by default as identity,
	address_id bigint not null
);
create table Address (
	id bigint not null primary key
		generated by default as identity,
);

'Spring > JPA' 카테고리의 다른 글

[JPA] 코틀린으로 엔티티 작성 시 고려할 점  (0) 2022.02.08
[JPA] Fetch - Eager, Lazy  (0) 2021.12.04
[JPA] 연관관계[1/2] - 양방향  (0) 2021.12.03
[JPA] JPA 사용 시 주의할 점  (0) 2021.12.03
[JPA/Hibernate] Hibernate 기초  (0) 2021.10.12