관계형 데이터베이스는 테이블 간 foreign key로 연관관계를 맺고 JOIN을 통해 테이블을 조회한다.
예를 들어 Parking 테이블과 Charge 테이블의 연관관계를 M:1 관계라 하자.
그렇다면 기본적으로 외래 키는 M 쪽인 Parking 테이블에 존재하고,
Parking JOIN Charge, Charge JOIN Parking 양쪽 모두에서 조회가 가능하다.
객체의 경우, Parking에 Charge 멤버 변수를 두어 관계를 맺는다.
Parking -> Charge 조회는 가능하지만, Charge -> Parking는 조회할 수 없다. 이러한 관계를 단방향 관계라 부른다.
그렇다면 JPA를 통해 연관관계가 어떻게 매핑되는지 자세히 알아보자.
@Entity
public class Parking {
@Id
@GeneratedValue
private Long id;
private String ParkingName;
@ManyToOne
@JoinColumn(name="charge_id")
private Charge charge;
}
@Entity
public class Charge {
@Id
@GeneratedValue
private Long id;
private String chargeName;
}
위 코드는 Parking 테이블에 외래 키인 charge_id가 생성되고, 단방향이기 때문에 Charge 엔티티에서는 Parking을 알 수 없다.
@ManyToOne : M:1 관계를 표현하는 어노테이션
양방향 매핑 코드를 봐보자.
@Entity
public class Parking {
@Id
@GeneratedValue
private Long id;
private String ParkingName;
@ManyToOne
@JoinColumn(name="charge_id")
private Charge charge;
}
@Entity
public class Charge {
@Id
@GeneratedValue
private Long id;
private String chargeName;
//양방향 매핑을 위한 추가
@OneToMany(mappedBy = "charge")
private List<Parking> parking = new ArrayList<>();
}
Charge에 Parking를 저장할 필드가 생성된 것을 볼 수 있고, @OneToMany 어노테이션이 사용됐다.
속성 mapppedBy는 양방향 매핑일 때 사용한다.
JPA는 두 개의 연관관계 중 하나를 고르게 하기 위해 mappedBy를 설정
mappedBy가 없는 엔티티가 연관관계의 주인
일반적으로 일대다 단방향 관계 매핑은 권장되지 않고, 다대일 단방향으로 관계를 맺는 것이 좋다.
일대다 양방향 관계는 존재하지 않는다.
양쪽이 서로 하나의 관계만 가진다.
외래 키가 어디에 있든 상관이 없다.
@Entity
public class Parking {
@Id
@GeneratedValue
private Long id;
private String ParkingName;
}
@Entity
public class Charge {
@Id
@GeneratedValue
private Long id;
private String chargeName;
@OneToOne
@JoinColumn(name = "parking_id")
private Parking parking
}
@Entity
public class Parking {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String ParkingName;
@OneToOne(mappedBy = "parking")
private Charge charge;
}
@Entity
public class Charge {
@Id
@GeneratedValue
private Long id;
private String chargeName;
@OneToOne
@JoinColumn(name = "parking_id")
// parking을 연관관계 주인으로 하고 싶다면 mappedBy, @joinColumn의 위치를 서로 바꿔준다.
private Parking parking;
}
두 테이블 사이에 중간 테이블을 두어 관계를 풀어줘야 하는데 실무에서 한계가 존재하기 때문에 지양하자.
중간 테이블을 묵시적으로 생성해 주기 때문에 복잡한 조인 쿼리가 발생
중간 테이블에 필요한 추가 컬럼을 사용할 수 없다.
@GeneratedValue(strategy = GenerationType.IDENTITY)
기본 키 생성을 데이터베이스에 위임
즉, id 값을 null로 하면 DB가 알아서 AUTO_INCREMENT