이 글은 백기선 님의 스프링 데이터 JPA 강의를 듣고 복습 차원에서 적은 글입니다.
이 글은 김영한 님의 자바 ORM 표준 JPA 프로그래밍 책을 읽고 복습 차원에서 적은 글입니다.
스프링 부트를 기반으로 환경설정을 했다.
JPA는 엔티티와 테이블을 매핑하고 DB 스키마를 자동으로 생성한다.
ddl_auto 옵션으로 로컬에서 편하게 스키마를 만들 수 있다.
applicaton.properties
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
JpaRunner.class
@Component
@Transactional
public class JpaRunner implements ApplicationRunner {
@PersistenceContext
EntityManager entityManager;
@Override
public void run(ApplicationArguments args) throws Exception {
// 회원 엔티티
Member member = new Member();
member.setUsername("giuly");
member.setPassword("1026");
// 강좌 엔티티
Course course = new Course();
course.setName("Spring Data JPA");
course.setMember(member);
// 관계의 주인은 Course 이다.
// member.getCourses().add(course);
// course.setMember(member);
member.addCourses(course);
// entityManager.persist(member);
Session session = entityManager.unwrap(Session.class);
session.save(member);
session.save(course);
}
Member.class
@Entity
// @Entity(name = "myMember") -> 객체의 이름을 따로 설정할 수 있다.
// @Table => 테이블 이름을 설정할 수 있다. Entity 객체의 이름이 디폴트 값이다.
public class Member {
@Id // PK
@GeneratedValue // 자동증가
private Long id; // Long vs long 차이가 있다. -> https://siyoon210.tistory.com/139
// @Column -> @Entity 생략 가능
// @Column(nullable = false, unique = true)
private String username;
private String password;
// TemporalType.Date : 년-월-일 의 date 타입
// TemporalType.Time : 시:분:초 의 time 타입
// TemporalType.TIMESTAMP : date + time 의 timestamp(datetime) 타입
@Temporal(TemporalType.TIMESTAMP)
private Date createDate = new Date();
// @Transient -> 테이블 컬럼으로는 사용하고 싶지 않을 때 사용한다.
@Transient
private String test;
@Embedded
// @AttributeOverrides({
// @AttributeOverride(name = "street", column = @Column(name = "home_street"))
// })
private Address address;
// @OneToMany // 단방향 상태이다.
// private Set<Course> courses = new HashSet<Course>();
@OneToMany(mappedBy = "member") // 양방향 상태이다.
private Set<Course> courses = new HashSet<Course>();
// Companion Method
public void addCourses(Course course) {
this.getCourses().add(course);
course.setMember(this);
}
public void removeCourses(Course course) {
this.getCourses().remove(course);
course.setMember(null);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
Course.class
@Entity
public class Course {
@Id @GeneratedValue
private Long id;
private String name;
// Many => One
@ManyToOne // FK
private Member member;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
}
Address.class
@Embeddable
public class Address {
private String street;
private String city;
private String state;
private String zipCode;
}
JPA 프로그래밍 : 엔티티 맵핑
@Entity
- 엔티티란 객체 세상에서 부르는 이름이다.
- 보통 클래스와 같은 이름을 사용한다.
- 엔티티의 이름은 JPAL에서 사용한다.
@Table
- 릴레이션 세상에서 부르는 이름이다.
- @Entity의 이름이 기본값이다.
- 테이블 이름은 SQL에서 사용한다.
@Id
- 엔티티의 주키를 매핑할 때 사용한다.
@GeneratedValue
- 주키의 생성 전략과 생성기를 설정할 수 있다.
@Column
- 컬럼을 제약조건과 타입 등을 설정할 수 있다.
@Temporal
- 현재 JPA2.1까지는 Date와 Calendar만 지원한다.
@Transient
- 컬럼으로 매핑하고 싶은 않은 멤버 변수에 사용한다.
JPA 프로그래밍 : Value 타입 맵핑
Value 타입의 종료는 3가지가 있다.
1. 기본값 타입
- 자바 기본 타입 (int, double)
- 래퍼 클래스 (Integer, Long)
- String
2. 임베디드 타입
- JPA에서 정의해서 사용해야 한다. (@Embeddable, @Embedded, @QAttributeOverrides, @AttributeOverride)
3. 컬렉션 값 타입
- JPA에서 정의해서 사용해야 한다.
- 컬렉션에 기본값 또는 임베디드 타입을 넣은 형태이다.
JPA 프로그래밍 : 1대다 맵핑
관계에는 항상 두 엔티티가 존재한다. 둘 중 하나는 그 관계의 주인이고, 다른 쪽은 종속된 부분이다.
단방향
- @ManyToOne (기본값은 FK를 생성한다.)
- @OneToMay (기본값은 조인 테이블을 생성한다.)
Hibernate:
insert into member
(city, state, street, zip_code, create_date, password, username, id)
values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert into course (member_id, name, id)
values (?, ?, ?)
Hibernate:
insert into member_courses
(member_id, courses_id)
values (?, ?)
Schema | Name | Type | Owner
--------+----------------+-------+------------
public | course | table | jihuni1026
public | member | table | jihuni1026
public | member_courses | table | jihuni1026
자동으로 member_courses라는 관계 테이블을 만들어 준다.
양방향
- @ManyToOne 내가 주인이다.
- @OneToMany(mappedBy) 주인한테 관계를 설정해야 DB에 반영된다.
Hibernate:
insert into member
(city, state, street, zip_code, create_date, password, username, id)
values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert into course
(member_id, name, id)
values (?, ?, ?)
Schema | Name | Type | Owner
--------+--------+-------+------------
public | course | table | jihuni1026
public | member | table | jihuni1026
단방향은 실제 테이블을 3개 운영해야 되기 때문에 양방향을 추천한다.
여기서는 JPA 사용법을 배웠습니다.
핵심만 정리하자면 JPA는 @Entitiy를 분석해서 자동으로 DB에 테이블을 생성한다.
엔티티 Value타입에는 기본값, 임베디드, 컬렉션 3가지가 있다.
맵핑에는 단방향과 양방향이 있다.
정도만 아시면 되겠습니다.
'BackEnd > JPA' 카테고리의 다른 글
[JPA] 스프링 데이터 JPA 이야기 번외편 - 영속성 컨텍스트 (0) | 2020.10.05 |
---|---|
[JPA] 스프링 데이터 JPA 이야기 1부 (0) | 2020.09.16 |
댓글