Programming/Spring Data JPA

JPA 프로그래밍 - 1 (스프링 데이터 JPA - 2)

흠냐아뤼 2020. 4. 30. 19:03
728x90

1. 개요 (기본)

 

- 의존성 추가 (spring data JPA와 관련된 빈들이 모두 등록됨)

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

 

- application.properties 추가

spring.datasource.url=jdbc:postgresql://localhost:5432/springdata
spring.datasource.username=hongchan
spring.datasource.password=pass

spring.jpa.hibernate.ddl-auto=create //update, validate
// 개발할 때는 create, 이후에는 validate 사용을 권장!
// update는 스키마 수정 시 지저분해질 수 있는 우려가 있음! 조심해서 사용

 

- 도메인 Account 객체 생성 @Entity

@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

    private String username;

    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsernmae() {
        return username;
    }

    public void setUsernmae(String usernmae) {
        this.username = usernmae;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

 

- JPA API 사용하기

@Component
@Transactional	// persist 사용 시 트랜잭션으로 처리해야 함
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;	// JPA API에서 가장 핵심적인 것

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Account account = new Account();
        account.setUsernmae("jiyun");
        account.setPassword("1234");

        entityManager.persist(account);
    }
}

 

- Hibernate API 사용하기

@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Account account = new Account();
        account.setUsernmae("jiyun2");
        account.setPassword("hibernate");

        Session session = entityManager.unwrap(Session.class);	// 핵심적인 API
        session.save(account);
    }
}

 

 

2. 엔티티 맵핑

 

@Entity

- 객체 세상에서 부르는 이름 (보통 클래스와 같은 이름을 사용하기 때문에 잘 변경하지 않음)

 

@Table

- 릴레이션 세상에서 부르는 이름

- @Entity의 이름이 기본 값

- 테이블의 이름은 SQL에서 쓰임

 

@Id

- 엔티티의 PK를 맵핑할 때 사용

 

@GeneratedValue

- PK의 생성 방법을 맵핑하는 애노테이션

 

@Column

- 보통 생략되어 있고, 추가적으로 명시할 때 사용

- (nullable = false, unique = true)

 

@Temporal

- Date, Calender

 

@Transient

- 컬럼으로 맵핑하고 싶지 않은 멤버에 추가

 

- 실행되는 SQL 문을 확인하는 설정 추가

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

 

 

3. Value 타입 맵핑

- Account 엔티티 타입 안에 있는 멤버들(id, username, password)

- 기본 타입, Composite Value 타입, Collection Value 타입

 

Composite Value 타입 맵핑

- @Embadable

- @Embadded

- @AttributeOverrides

- @AttributeOverride

 

@Embeddable
public class Address {

    private String city;

    private String state;

    private String street;

}
@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

	...

    @Embedded
    private Address address;
}
// 실행된 SQL
create table account (
       id int8 not null,
        city varchar(255),
        state varchar(255),
        street varchar(255),
        password varchar(255),
        username varchar(255),
        primary key (id)
    )

 

 

4. 1대다 맵핑

- 관계에는 항상 두 엔티티가 존재함

- 둘 중 하나는 그 관계의 주인이고, 다른 쪽은 종속된 쪽이다.

- 해당 관계의 반대쪽 레퍼런스를 가지고 있는 쪽이 주인

 

 

@ManyToOne

- Study 가 이 관계에서 주인이 됨. (단방향에서는 관계를 정의한 쪽이 주인)

- 종속된 쪽의 PK를 FK로 설정함

 

(Getter Setter 생략)

- Account.java

@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

    private String username;

    private String password;

}

 

- Study.java

@Entity
public class Study {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    private Account owner;

}

 

@OneToMany

- Account가 관계의 주인이 됨 (단방향에서는 관계를 정의한 쪽이 주인)

- Join 테이블 생성 'account_studies'

 

- Account.java

@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

    private String username;

    private String password;

    @OneToMany
    private Set<Study> studies = new HashSet<>();

}

 

- Study.java

@Entity
public class Study {

    @Id @GeneratedValue
    private Long id;

    private String name;

}

 

양방향 관계

- 기본적으로 FK를 가진쪽(@ManyToOne)이 주인이 됨!

- @OneToMany 쪽에 mappedBy를 사용해 관계를 맺고 있는 필드를 설정해주어야 함!! (주인한테 관계를 설정해야 DB에 반영이 됨)

- Account.java의 addStudy, removeStudy 메소드 처럼 구현하여 보통 양쪽에 데이터를 넣거나 삭제시켜 일치시킴.

   -> 주인인 쪽에만 설정하면 DB에 반영이 되지만 양방향을 고려하여 양쪽에 데이터를 일치시킴

 

- Account.java

@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

    private String username;

    private String password;

    @OneToMany(mappedBy = "owner")
    private Set<Study> studies = new HashSet<>();
    
    ...

    public void addStudy(Study study) {
        this.getStudies().add(study);
        study.setOwner(this);		// 주인에 설정
    }

    public void removeStudy(Study study) {
        this.getStudies().remove(study);
        study.setOwner(null);		// 주인에 설정
    }
}

 

- Study.java

@Entity
public class Study {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    private Account owner;

}

 

 

 

인프런 백기선님 '스프링 데이터 JPA’ 강의를 듣고 정리한 내용입니다.
728x90