WEEK 6-13: Spring Entity

ensalada.de.pollo·2025년 5월 18일

be

목록 보기
35/44

@Entity와 @Table

@Entity

클래스에 @Entity를 선언하면 JPA가 관리하는 엔티티로 인식하게 됩니다.

필수 조건

  • PK(@Id) 필드가 반드시 존재해야 함
  • 기본 생성자 필요
  • final, enum, interface, inner class에는 사용이 불가능
  • 필드에 final 사용 불가능

name 속성으로 엔티티 이름 지정이 가능합니다.

@Table

엔티티와 매핑할 테이블 이름, 스키마, 유니크 제약 조건들을 지정합니다.
생략하면 엔티티의 이름이 테이블 이름이 됩니다.

예시

@Entity
@Table(name = "tutor")
public class Tutor {
    @Id
    private Long id;
    private String name;
    public Tutor() {}
    public Tutor(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

DDL 자동 생성 옵션(hibernate.hbm2ddl.auto)

설명
create기존 테이블 DROP 후 CREATE
create-drop시작 시 DROP + CREATE, 종료시 DROP
update변경 사항만 ALTER, 기존 데이터 유지
validate엔티티와 테이블 매핑만 검증, 불일치 시 제외
none자동 DDL 생성 또는 검증 없음

실무에서는 validate, none 사용을 권장하며, 개발 단계에서는 create, create-drop, update를 상황에 맞게 사용합니다.

Entity 필드 매핑과 주요 어노테이션

  • @Column: 컬럼명, 길이, null 허용, 유니크 등 제약조건 설정
  • @Enumerated: enum 타입 매핑(ORDINAL: 숫자, STRING: 이름)
  • @Temporal: 날짜 및 시간 타입 지정(DATE, TIME, TIMESTAMP)
  • @Transient: DB 컬럼과 매핑하지 않음(임시 필드)
  • @Lob: 대용량 데이터 매핑
@Column(unique = true, length = 20, nullable = false)
private String name;

@Enumerated(EnumType.STRING)
private BoardType boardType;

@Column(columnDefinition = "longtext")
private String contents;

@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;

@Transient
private int count;

Timestamp에 관해서

최신 버전 Hibernate에서 LocalDate, LocalDateTime은 @Temporal 생략이 가능합니다.

PK 생성 전략

  • @Id: 수동 지정
  • @GeneratedValue: 자동 생성
    • GenerationType.IDENTITY: MMYSQL, PostgreSQL(AutoIncrement)
    • GenerationType.SEQUENCE: Oracle(sequence)
    • GenerationType.TABLE: 키 생성용 테이블 사용
    • GenerationType.AUTO: DB 방언에 따라 자동 선택, 권장하지는 않음
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

제약 조건 설정

  • @Column: unique, nullable, length 등의 속성으로 DDL 제약 조건 설정
  • @Table: uniqueConstraints로 복합 유니크 제약조건 설정
@Column(unique = true, length = 20, nullable = false)
private String name;

@Table(uniqueConstraints = {
    @UniqueConstraint(name = "name_unique", columnNames = {"name"})
})

단방향 연관관계

한 객체만 다른 객체를 참조하는 관계를 의미합니다.
예를 들어서, Tutor가 Company만 참조하는 경우가 있습니다. 이때, Company는 Tutor를 알지 못합니다.

특징

  • 설정이 단순하고 유지보수가 쉽습니다.
  • 불필요한 데이터의 접근을 방지할 수 있습니다.
  • 데이터베이스에서는 FK만으로 양쪽 조인이 가능하지만, 객체에서는 참조 필드가 있는 쪽만 다른 객체에 접근이 가능합니다.

예시

@Entity
@Table(name = "tutor")
public class Tutor {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "company_id")
    private Company company;
    // ...
}

Tutor만 Company를 참조할 수 있습니다. 즉, tutor.getCompany()는 가능하지만, company.getTutors()는 불가능합니다.

양방향 연관관계

양쪽 객체가 서로를 참조하는 관계입니다. 예를 들면, Tutor와 Company가 서로를 참조하는 경우가 있습니다.

특징

  • 두 객체 모두 상대 객체에 접근이 가능합니다.
  • 객체 그래프 탐색이 자유롭습니다.
  • 테이블에는 변화가 없고, 객체 차원에서만 방향이 생깁니다.

예시

@Entity
@Table(name = "company")
public class Company {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @OneToMany(mappedBy = "company")
    private List<Tutor> tutors = new ArrayList<>();
    // ...
}

Company에서 Tutor 리스트를 참조할 수 있습니다.
mappedBy = "company"로 Tutor의 company필드가 연관관계의 주인임을 명시합니다.

mappedBy

연관관계의 주인

두 객체가 양방향 관계일 때, 실제로 외래키를 관리하는 쪽을 의미합니다. 즉, 외래키가 있는 엔티티가 주인이 되는 것입니다.

주인은 mappedBy 속성을 사용하지 않고, 주인이 아닌 쪽만 mappedBy를 사용합니다.

주인과 비주인의 구분

주인은 외래키 필드가 있는 엔티티이며 등록, 수정, 삭제 등 관계의 제어가 가능합니다.
비주인은 mappedBy로 주인 필드명을 지정, 조회만 가능합니다.

// Tutor (주인)
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;

// Company (비주인)
@OneToMany(mappedBy = "company")
private List<Tutor> tutors;

규칙

  • 두 엔티티 중 하나를 반드시 연관관계의 주인으로 지정해야 합니다.
  • 주인은 mappedBy를 사용하지 않습니다.
  • 비주인은 mappedBy를 사용해 주인을 명시합니다.
  • 주인만 외래키를 관리할 수 있습니다.
  • 비주인은 조회만 가능합니다.

자료 및 코드 출처: 스파르타 코딩클럽

0개의 댓글