[SpringBoot 환경에서의 JPA 설정]
build.gradle
// JPA 설정
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// MySQL
implementation 'mysql:mysql-connector-java:8.0.28'
application.properties : Hibernate 설정
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
[ddl-auto]
- create : 기존 테이블 삭제 후 다시 생성합니다. (DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블을 DROP 합니다.
- update : 변경된 부분만 반영합니다.
- validate : Entity와 테이블이 정상 매핑되었는지만 확인합니다.
- none: 아무것도 하지 않습니다.
[show_sql, format_sql, use_sql_comments 옵션]
- Hibernate가 DB에 요청하는 모든 SQL을 보기좋게 출력 해줍니다.
Entity
@Entity // JPA가 관리할 수 있는 Entity 클래스 지정
@Table(name = "memo") // 매핑할 테이블의 이름을 지정
public class Memo {
// 테이블의 기본 키를 지정
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // // auto_increment 조건
private Long id;
// nullable: null 허용 여부
// unique: 중복 허용 여부 (false 일때 중복 허용)
@Column(name = "username", nullable = false, unique = true)
private String username;
// length: 컬럼 길이 지정
@Column(name = "contents", nullable = false, length = 500)
private String contents;
}
Persistence를 한글로 번역하면 영속성, 지속성 이라는 뜻
객체가 유지되는 시간이나 객체의 위치을 자유롭게 유지하고 이동할수 있는 객체의 성질
Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간
JPA는 영속성 컨텍스트에 Entity 객체들을 저장하여 관리하면서 DB와 소통한다.
영속성 컨텍스트에 접근하여 Entity 객체들을 조작하기 위해서는 EntityManager가 필요
개발자들은 EntityManager를 사용해서 Entity를 저장하고 조회하고 수정하고 삭제할 수 있다.
EntityManager는 EntityManagerFactory를 통해 생성하여 사용할 수 있다.
EntityManagerFactory는 일반적으로 DB 하나에 하나만 생성되어 애플리케이션이 동작하는 동안 사용된다.
EntityManagerFactory를 만들기 위해서는 DB에 대한 정보를 전달해야헌다.
정보를 전달하기 위해서는 /resources/META-INF/ 위치에 persistence.xml 파일을 만들어 정보를 넣어두면 된다.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="memo">
<class>com.sparta.entity.Memo</class>
<properties>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="{비밀번호}"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/memo"/>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
트랜잭션은 DB 데이터들의 무결성과 정합성을 유지하기 위한 하나의 논리적 개념
JPA는 DB의 이러한 트랜잭션 개념을 사용하여 효율적으로 Entity를 관리한다.
DB에서 하나의 트랜잭션에 여러 개의 SQL을 포함하고 있다가 마지막에 영구적으로 변경을 반영하는 것 처럼
JPA에서도 영속성 컨텍스트로 관리하고 있는 변경이 발생한 객체들의 정보를 쓰기 지연 저장소에 전부 가지고 있다가 마지막에 SQL을 한번에 DB에 요청해 변경을 반영한다.
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
...
@Transactional
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
...
}
readOnly = true
옵션 : 트랜잭션에서 데이터를 읽기만 할 때(조회의 경우) 사용된다.영속성 컨텍스트는 내부적으로 캐시 저장소를 가지고 있다.
'1차 캐시' 사용의 장점
1. DB 조회 횟수를 줄임
2. '1차 캐시'를 사용해 DB row 1개 당 객체 1개가 사용되는 것을 보장 (객체 동일성 보장)
캐시 저장소에 조회하는 Id가 존재하지 않은 경우
1) 캐시 저장소 조회
2) DB SELECT 조회 후 캐시 저장소에 저장
캐시 저장소에 조회하는 Id가 존재하는 경우
호출 시 캐시 저장소에 식별자 값이 1이면서 Memo Entity 타입인 값이 있는지 조회
값이 있다면 해당 Entity 객체를 반환
삭제할 Entity를 조회한 후 캐시 저장소에 없다면 DB에 조회해서 저장
em.remove(memo); 호출 시 삭제할 Entity를 DELETED 상태로 만든 후 트랜잭션 commit 후 Delete SQL이 DB에 요청
JPA에서는 Update를 어떻게 처리할까? 아래와 같은 과정은 변경 감시라고 부른다.
em.flush();
가 호출되면 Entity의 현재 상태와 저장한 최초 상태를 비교