엔티티 매핑

@Entity : JPA를 사용해 테이블과 매핑할 클래스로 지정하는 어노테이션.

  • 기본생성자가 반드시 필요하다.
  • final, enum, interface, inner 클래스에 사용할 수 없다.
  • 저장할 필드에 final을 사용할 수 없다.
  • name : 기본값으로 클래스명이 사용된다. 다른 패키지에서 중복 클래스명이 엔티티로 사용된다면 충돌을 막기위해 값 설정이 필요하다.

@Table : 엔티티와 매핑할 테이블을 지정하는 어노테이션.

  • name : 테이블명을 지정할 때 사용된다.(default 엔티티명)
  • uniqueConstraints : DDL 생성 시에 유니크 제약조건을 만든다. 복합 유니크 제약조건도 가능하다. 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용된다.
@Table(name = "t_user", indexes = { @Index(name = "idx_u_username", columnList = "username") }, 
uniqueConstraints = @UniqueConstraint(name="uk_user", columnNames = {"email", "username" }))

스키마 자동 생성

  • 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성한다.
  • DDL은 운영환경에서 사용할 만큼 완벽하지는 않으므로 개발 환경에서 사용하거나 매핑을 어떻게 해야하는지 참고하는 정도로만 사용한다.
  • 자동 생성되는 DDL은 지정한 데이터베이스 방언에 따라 달라진다. ex) mysql : varchar, integer / oracle : varchar2, number

스키마 자동 생성 종류

create : 기존 테이블 삭제후 다시 생성. drop + create
create-drop : 위 과정에 추가로 앱 종료시 DDL 제거. drop + create + drop
update : DB 테이블과 엔티티 매핑정보를 비교해 변경사항만 수정.
validate : DB 테이블과 엔티티 매핑정보를 비교해 차이가 있으면 경고. 앱 실행X. DDL 변경X.
none : 자동생성기능 사용안함.

JPA 기본 환경설정

@Configuration
public class DataConfig {

    @Autowired
    private DatabaseProperties databaseProperties;

    @Bean
    public DataSource dataSoure(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(databaseProperties.getDriver());
        dataSource.setUrl(databaseProperties.getUrl());
        dataSource.setUsername(databaseProperties.getUsername());
        dataSource.setPassword(databaseProperties.getPassword());
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSoure());
        factoryBean.setPackagesToScan("com.example.model");
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

        // JPA 상세설정
        Properties jpaProperties = new Properties();
        jpaProperties.put(AvailableSettings.SHOW_SQL, true); // SQL 보기
        jpaProperties.put(AvailableSettings.FORMAT_SQL, true); // SQL 포맷팅하기
        jpaProperties.put(AvailableSettings.USE_SQL_COMMENTS, true); // SQL 코멘트 보기
        jpaProperties.put(AvailableSettings.HBM2DDL_AUTO, databaseProperties.getHbm2ddlAuto()); // DDL 자동생성 종류
        jpaProperties.put(AvailableSettings.DIALECT, databaseProperties.getDialect()); // 방언 설정
        jpaProperties.put(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, true); // 키 생성 전략 사용시 설정
        jpaProperties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy"); // 자바의 카멜 표기법을 테이블의 언더스코어 표기법으로 매핑
        factoryBean.setJpaProperties(jpaProperties);

        return factoryBean;
    }
}

기본키 매핑

  • 직접 할당 : @Id & Setter
    Board board = new board();
    board.setId("id1");
    em.persist(board); 
    // @Id로 지정한 id 필드에 Set메소드로 직접 할당하는 방법
  • 자동 생성 : 대리키 사용 방식. @GeneratedValue

영속성 컨텍스트는 엔티티를 영속 상태로 만드려면 식별자 값이 반드시 있어야 한다.
@Id, @GeneratedValue(strategy = GenerationType.매핑전략, generator = 식별자 생성기 이름)

GenerationType.IDENTITY

  • 기본키 생성을 DB에 위임하는 전략.
  • DB 종속적. Mysql, PostgreSQL, SQL SERVER
  • DB 저장시 @Id 컬럼을 비워두면 DB가 순서대로 값을 채워준다.
  • 전략 사용시 JPA는 기본키 값을 얻어오기 위해 DB를 추가로 조회한다.
  • statement.getGerenatedkey() 사용하면 데이터를 저장하면서 동시에 기본키 값을 얻어와서 DB를 한번만 조회한다.
  • 트렌잭션을 지원하는 쓰기 지연이 동작하지 않는다.

GenerationType.SEQUENCE

  • DB 시퀀스를 사용해 기본키를 할당한다.
  • DB 종속적. Oracle, H2, DB2
  • 엔티티나 컬럼에 @SequenceGenerator 표기
    • name : 식별자 생성기 이름
    • sequenceName : DB 시퀀스명
    • initialValue : 시퀀스 시작 값 (default 1)
    • allocationSize : 시퀀스 호출 시 증가 수 (default 50)
  • DB 시퀀스를 사용해 식별자를 조회해 엔티티에 할당 후, 엔티티를 영속성 컨텍스트에 저장하고 트랜잭션을 커밋하면 DB에 저장된다.

GenerationType.TABLE

  • 엔티티에 @TableGenerator 표기
    • name : 식별자 생성기 이름 (필수)
    • table : 키 생성 테이블명
    • pkColumnName : 시퀀스 컬럼명
    • valueColumnName : 시퀀스 값 컬럼명
  • 키 생성 전용 테이블 만들고 이름과 같은 값으로 사용할 컬럼을 생성한다.
  • 내부 동작은 SEQUENCE와 같다.
Sequence 테이블 생성 DDL

CREATE TABLE MY_SEQUENCE{
  SEQUENCE_NAME VARCHAR(255) NOT NULL,
  NEXT_VAL BIGINT,
  PRIMARY KEY (SEQUENCE_NAME)
}
TABLE 전략 매핑 코드

@Entity
@TableGenerator(
 name = "BOARD_SEQ_GENERATOR",
 table = "MY_SEQUENCE",
 pkColumnValue = "BOARD_SEQ",
 allocationSize = 1)
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "BOARD_SEQ_GENERATOR")
    private Long id;
}

GenerationType.AUTO

  • DB 방언에 따라 위의 전략 중 하나를 자동으로 선택한다. ex) MySQL : IDENTITY
  • DB 변경시 코드를 수정할 필요가 없다.
  • SEQUENCE 전략이 사용되면 하이버네이트가 기본값을 사용해서 적절한 시퀀스를 만들어준다.

권장 식별자 선택 전략

  • 기본키 조건 : NOT NULL, 유일 값, 불변
  • 기본키 선택전략
    • 자연키 : 비즈니스에 의미가 있는 키. ex) email, 주민등록번호 등
    • 대리키(대체키) : 비즈니스에 무관한 임의의 키. ex) uuid, sequence, auto_increment 등

필드와 컬럼 매핑

@Column : 객체 필드를 테이블 컬럼과 매핑시킨다.

  • name(default 필드명) : 필드와 매핑할 컬럼명
  • nullable(default true) : null 허용 여부.
  • unique(default false) : 컬럼에 유일값 허용 여부.
  • length(default 255) : 문자길이 제약조건. String 필드에만 사용한다.
  • columnDefinition : 직접 정의 "varchar(10) default 'test'". 사용하는 DB 종류에 종속될 수 있으므로 지양한다.
  • insertable,updatable(default true) : 읽기전용시 false로 설정하여 DB에 저장/수정이 불가하도록 지정한다.자바 기본(primitive)타입에 @Column을 사용하면 nullable = false로 지정하는 것이 안전하다.

@Enumerated : 열거 타입 매핑

  • EnumType.ORDINAL(default) - enum 순서를 DB에 저장하기 때문에 순서가 변경될 경우 안전하지 못하다.
  • EnumType.STRING - enum 이름을 DB에 저장하기 때문에 안전하다.

@Temporal : 날짜 타입 매핑

  • TemporalType.DATE > 2013-10-11
  • TemporalType.TIME > 11:11:11
  • TemporalType.TIMESTAMP(default) > 2013-10-11 11:11:11

@Lob : CLOB,BLOB 타입 매핑

  • CLOB : 문자. String, char[], CLOB (mysql : longtext / oracle : clob)
  • BLOB : 나머지. byte[], BLOB (mysql : longblob / oracle : blob)

@Transient : 특정 필드 매핑 제외

  • 컬럼과 매핑하지 않으므로 DB에 저장하지 않는다.
  • 객체 필드에 임시로 데이터를 보관하는 용도. ex) 비밀번호/확인비밀번호 값을 객체 필드로 각각 입력받아 동일한 값인지 확인

@Access : JPA가 엔티티에 접근하는 방식 지정. @Id 대체

  • AccessType.FIELD : 필드에 직접 접근한다. 필드 접근 권한이 private 이어도 접근이 가능하다.
  • AccessType.PROPERTY : 접근자 Getter를 사용해 접근한다.
    @Id가 필드에 있냐 프로퍼티에 있냐에 따라 access 방식이 달라진다.

  • AccessType이 FIELD로 정의된 경우 영속화 과정에서 필드에 데이터를 설정하거나 읽어올 때, 
    메소드를 통하지 않고 직접 필드에 접근해서 읽어오기 때문에 Get/Set 메소드에 별도의 로직이 존재하는 경우 동작하지 않는다.

  • 반대로 필드명과 Get메소드의 이름이 다를 때, 별도의 로직을 통해 변환된 값을 DB에 저장하고 싶다면@Transient 어노테이션을 필드에 부여해 영속화에서 제외시키고 Get메소드에 @Access(AccessType.PROPERTY)를 설정하면 된다.
@Entity
public class Member {

    @Id
    private String id;

    @Transient
    private String firstName;

    @Transient
    private String lastName;

    @Access(AccessType.PROPERTY)
    public String getFullName(){
        return this.firstName + this.lastName;
    }
 }
// @Id가 필드에 있으므로 필드 접근 방식을 사용하고 getFullName만 프로퍼티를 사용한다.
// Member 엔티티에 fullName 컬럼이 생성되고 firstName + lastName의 결과가 저장된다.


참고서적 - 자바 ORM 표준 JPA 프로그래밍 (김영한)

'Development > JPA' 카테고리의 다른 글

영속성 관리  (0) 2017.01.21
JPA 시작  (0) 2016.11.20
JPA 소개  (0) 2016.05.04

영속성 관리


* 엔티티 매니저 팩토리 & 엔티티 매니저
엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드 간에 공유해도 되지만,
엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대 공유하면 안된다.

1
2
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
EntitiManager em = emf.createEntityManger();

cs


데이터베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않고 트랜잭션을 시작할 때 커넥션을 획득한다.

영속성 컨텍스트
- 엔티티 매니저 생성시 생성되는 엔티티 영구 저장 환경.
- 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.

* 엔티티의 생명주기
비영속(New/Transient) : 영속성 컨텍스트와 전혀 관계 없는 상태. 엔티티 객체 생성후 저장되지 않은 상태.
영속(Managed) : 영속성 컨텍스트에 저장된 상태. 영속성 컨텍스트에 의해 관리된다.
준영속(Detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태. 영속성 컨텍스트에 의해 관리되지 않는다.
삭제(Removed) : 삭제된 상태. 영속성 컨텍스트와 DB에서 삭제된 상태.

* 영속성 컨텍스트 특징
- 영속 상태는 식별자 값이 반드시 있어야 한다.
- 트랜잭션을 커밋하는 순간 영속성 컨텍스에 새로 저장된 엔티티를 DB에 반영한다. flush
- 장점) 1차 캐시, 동일성 보장, 트랜잭션을 지원하는 쓰기 지연, 변경감지, 지연로딩. (CRUD 통해 설명)

# 엔티티 조회 em.find(entity class, key)
1차 캐시 : 영속 상태의 엔티티 저장소로 Map 형태에 @Id로 매핑할 식별자와 엔티티 인스턴스 값을 저장한다.
동일성 보장 : 조회 쿼리 호출시 1차 캐시에서 엔티티를 찾고, 없으면 DB에서 조회하여 1차 캐시에 저장시킨 후 엔티티를 반환한다.
지연로딩 : 일대다 혹은 다대다 관계의 컬렉션을 실제 사용하는 시점까지 DB 조회를 지연한다. (자세한 내용은 다음 챕터에..)
- JPA는 1차 캐시를 통해 REPEATABLE READ 레벨의 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 차원에서 제공한다는 장점이 있다.

# 엔티티 등록 : em.persist(entity)
트랜잭션을 지원하는 쓰기 지연 : 엔티티 메니저는 트랜잭션을 커밋하기 전까지 엔티티를 DB에 저장하지 않고 쓰기 지연 SQL 저장소에 등록 쿼리를 쌓아 놓는다. 그리고 커밋시에 한번에 SQL을 DB에 전달한다.
- 트랜잭션 커밋 직전에만 DB에 SQL을 전달하면 되기 때문에 쓰기지연이 가능하다. 쿼리를 한번에 전달해서 성능을 최적화할 수 있다.

# 엔티티 수정 
스냅샷 : 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 둔다.
변경감지 : 엔티티의 변경사항을 DB에 자동으로 반영한다. 트랜잭션을 커밋하면 엔티티 매니저 내부에서 플러시가 호출된다. 엔티티와 스냅샷을 비교해 변경된 엔티티가 있으면 쓰기 지연 SQL 저장소에 수정 쿼리를 쌓아 놓고 한번에 SQL을 DB에 전달한다.

# 엔티티 삭제 : em.remove(entity)
- 삭제할 엔티티를 우선 조회한다. 그리고 삭제하면 삭제 쿼리를 쓰기 지연 SQL 저장소에 쌓아 놓는다. 그리고 커밋시에 한번에 SQL을 DB에 전달한다.
- 삭제를 요청한 엔티티는 영속성 컨텍스트에서 제거되므로 사용하지 말고 가비지 컬렉션의 대상이 되도록 두는 것이 좋다.

* 플러시 : em.flush()
- 트랜잭션을 커밋하는 순간 영속성 컨텍스트의 변경 내용을 DB에 동기화한다.
- 플러시 실행시 변경감지가 동작해서 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교해서 수정된 엔티티를 찾아 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록한다. 쓰기 지연 SQL 저장소의 쿼리를 DB에 전달한다. (등록/수정/삭제 쿼리)
- 영속성 컨텍스트를 플러시하는 방법은 다음과 같다.
1) em.flush() 직접 호출 - 테스트 외에 거의 사용하지 않는다.
2) 트랜잭션 커밋시 자동 호출
3) JPQL 쿼리 실행시 자동 호출

* 준영속
- 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.
- 비영속 상태와 흡사하지만 식별자 값은 가지고 있다.
- 영속 상태의 엔티티를 준영속 상태로 만드는 방법은 다음과 같다.
1) em.detach(entity) - 특정 엔티티를 영속성 컨텍스트로부터 분리. 1차 캐시와 쓰기 지연 SQL 저장소에 해당 엔티티를 관리하는 정보 제거한다.
2) em.clear() - 영속성 컨텍스트 초기화. 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만든다.
3) em.close() - 영속성 컨텍스트를 종료해 모두 준영속 상태가 된다.

* 병합 : em.merge(entity) 
- 파라미터로 넘어온 엔티티의 식별자 값으로 1차 캐시를 조회하고 찾는 엔티티가 없으면 DB에서 조회한다. DB에도 없으면 새로운 엔티티를 생성해 반환한다. 
따라서, 준영속/비영속 상태에 관계없이 영속 상태의 엔티티를 반환하는 insert/update 기능을 수행한다.


참고서적 - 자바 ORM 표준 JPA 프로그래밍 (김영한)
그림으로 이해를 돕는 http://www.slideshare.net/zipkyh/ksug2015-jpa3-jpa

'Development > JPA' 카테고리의 다른 글

엔티티 매핑  (0) 2017.11.12
JPA 시작  (0) 2016.11.20
JPA 소개  (0) 2016.05.04
JPA 시작

* pom.xml 설정 
- hibernate-core : 하이버네이트 라이브러리
- hibernate-entitymanager : 하이버네이트가 JPA구현체로 동작하도록 JPA 표준을 구현한 라이브러리
- hibernate-jpa-2.1-api : JPA2.1 표준 API를 모아둔 라이브러리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
<properties>
  <hibernate.version>버전</hibernate.version>
</properties>
 
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>${hibernate.version}</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>${hibernate.version}</version>
  <exclusions>
    <exclusion>
      <artifactId>commons-collections</artifactId>
      <groupId>commons-collections</groupId>
    </exclusion>
  </exclusions>
</dependency>
..
cs

* 객체 매핑
1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
@Table(name="MEMBER")
public class Member {
 
    @Id
    @Column(name = "ID")
    private String id;
 
    @Column(name = "NAME")
    private String username;
 
    private Integer age;
}
cs
- @Entity : 클래스를 테이블과 매핑한다고 JPA 에게 알림. 엔티티 클래스라고함.
- @Table : 엔티티 클래스에 매핑할 테이블 정보를 알림. 생략시 클래스이름을 테이블 이름으로 매핑함.
- @Id : 엔티티 클래스의 필드를 테이블의 기본 키에 매핑함.
- @Column : 필드를 컬럼에 매핑함. 생략시 필드명으로 컬럼명에 매핑함. 대소문자를 구분하는 데이터베이스 사용시 명시적으로 매핑해야함.


* persistence.xml 설정 
: JPA를 실행하기 위한 기본 설정파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
  <persistence-unit name="jpabook">
    <properties>
      <!-- 필수 속성 -->
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> // JDBC 드라이버
      <property name="javax.persistence.jdbc.user" value="root" /> // DB 접속 아이디
      <property name="javax.persistence.jdbc.password" value="" /> // DB 접속 비밀번호
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/test" /> // DB  접속 URL
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> // DB 방언
 
      <!-- 옵션 -->
      <property name="hibernate.show_sql" value="true" /> // 실행 쿼리문 출력여부
      <property name="hibernate.format_sql" value="true" /> // 쿼리문 정렬 출력여부
      <property name="hibernate.use_sql_comments" value="true" /> // 쿼리문 주석 출력여부
      <property name="hibernate.hbm2ddl.auto" value="validate" /> // 스키마 자동 생성
    </properties>
  </persistence-unit>
</persistence>
cs

- META-INF/persistence.xml 클래스 패스 경로에 있으면 별도의 설정 없이 JPA가 인식함.
- JPA 설정은 영속성 유닛으로부터 시작하는데 일반적으로 연결할 데이터베이스당 하나의 영속성 유닛을 등록함. 고유한 이름을 사용해야함.
- javax.persistence로 시작하는 속성은 JPA 표준 속성으로 특정 구현체에 종속되지 않음. 
  반면에 hibernate로 시작하는 속성은 하이버네이트 전용 속성이므로 하이버네이트에서만 사용 가능함.
hibernate.hbm2ddl.auto : 데이터베이스 스키마 자동 생성 설정
> create : 기존 테이블 삭제 후 재생성. 초기 개발시 사용.
> create-drop : create와 동일하나 종료시 테이블 삭제. 초기 개발시 사용.
> update : 스키마 변경 내역 반영. 초기 개발시 사용 .운영 DB에 사용해서는 안됨.
> validate : 엔티티와 테이블의 매핑 정상 여부 체크. 비정상시 예외 발생. 운영 DB에 사용.

* 데이터베이스 방언
- JPA는 애플리케이션에 특정 DB에 종속되지 않게 하는 벤더독립성을 가짐.
  하지만 각 데이터베이스마다 데이터 타입, 함수명, 페이징처리 등이 다르기 때문에
  SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능을 JPA에서는 방언(Dialect)라고함.

- 데이터베이스가 변경되어도 애플리케이션 코드를 변경할 필요없이 데이터베이스 방언만 교체하면됨.

- 대표적인 방언
  Mysql : org.hibernate.dialect.MySQLDialect
  Oracle : org.hibernate.dialect.OracleDialect
  H2 : org.hibernate.dialect.H2Dialect

* 애플리케이션 개발

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class JpaMain {
 
  public static void main(String[] args) {
 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook"); //엔티티 매니저 팩토리 생성
    EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성
    EntityTransaction tx = em.getTransaction();   //트랜잭션 기능 획득
    
    try {
      tx.begin();    //트랜잭션 시작
      logic(em);     //비즈니스 로직
      tx.commit();   //트랜잭션 커밋
    } catch (Exception e) {
      e.printStackTrace();
      tx.rollback(); //트랜잭션 롤백
    } finally {
      em.close();    //엔티티 매니저 종료
    }
      emf.close();   //엔티티 매니저 팩토리 종료
    }
 
  }
 
}
cs

- 엔티티 매니저 팩토리 생성
persistence.xml 의 설정 정보를 조회해 이름이 jpabook인 영속성 유닛 persistence-unit을 찾아서 엔티티 매니저 팩토리를 생성.
설정 정보를 읽어서 JPA를 동작 시키기 위한 기반 객체를 만들고 JPA 구현체에 따라 데이터베이스 커넥션 풀도 생성.
엔티티 매니저 팩토리를 애플리케이션 전체에서 딱 한번만 생성하고 공유해서 사용해야함.

- 엔티티 매니저 생성
엔티티 매니저 팩토리에서 엔티티 매니저 생성.
JPA 기능 대부분은 엔티티 매니저가 제공함.
엔티티 매니저를 사용해서 엔티티를 데이터베이스에 등록/수정/삭제/조회 할 수 있음.
엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드간에 공유하거나 재사용해서는 안됨.

- 트랜잭션 관리
엔티티 매니저에서 트랜잭션 API를 받아서 사용함.
비즈니스 로직이 정상 동작하면 트랜잭션을 커밋하고, 예외가 발생하면 트랜잭션을 롤백함.

- 비즈니스 로직
  저장 : em.persist(Object);
  조회 : em.find(Object, PK);
  삭제 : em.remove(Object);
  수정 : 엔티티 매니저를 통해 객체를 조회하여 Setter 메소드를 통해 값 변경. JPA의 변경감지 기능을 통해 수정.

- 엔티티 매니저 팩토리 & 엔티티 매니저 종료
사용이 끝난 엔티티 매니저는 반드시 종료해야함.
애플리케이션을 종료할 때는 엔티티 매니저 팩토리도 종료해야함.


참고서적 - 자바 ORM 표준 JPA 프로그래밍(김영한)

'Development > JPA' 카테고리의 다른 글

엔티티 매핑  (0) 2017.11.12
영속성 관리  (0) 2017.01.21
JPA 소개  (0) 2016.05.04
JPA 소개


* JPA 사용 전 

- 거듭 반복되는 코드
1. CRUD 기능 구현을 위한 SQL 작성
SELECT id, name FROM Member WHERE id = ?

2. JDBC API를 사용해 SQL 실행
ResultSet rs = stmt.executeQuery(sql);

3. 결과 값을 객체로 매핑
String id = rs.getString("id");
String name = rs.getString("name");
Member member = new Member();
member.setId(id);
member.setNam(name);
: SQL Mapper의 사용으로 JDBC API 코드를 덜어주지만 SQL 작성은 해야 한다.

- DB 스키마 변경에 따른 코드 수정 복잡

- 패러다임 불일치

객체
관계형 데이터베이스
상속
상속
슈퍼타입과 서브타입
연관관계
참조
외래키를 통해 조인
객체 그래프 탐색
참조를 통해 제한없이 탐색
SQL 조인 범위에 따른 탐색 범위 고정
비교
== 주소값 비교 
equals() 객체 내부 값 비교
PK로 각 row 구분
모델링
객체 지향 모델링
데이터 모델링
: 개발자가 객체와 관계형 데이터베이스 사이의 패러다임 불일치 문제를 해결하는 데 많은 시간과 코드 소요


* JPA 소개

- 개발자가 직접 SQL을 작성하지 않고 JPA가 제공하는 API를 사용하면 JPA가 적절한 SQL을 생성해 DB에 전달

- 자바 진영의 ORM 기술 표준 (객체와 관계형 데이터베이스 테이블 사이의 매핑 처리를 하여 각각 객체모델링과 데이터모델링 가능)

- JPA 동작 구조

- JPA 사용 이유
  표준  다른 구현 기술로 변경 용이
  성능  동일 트랜잭션 내 데이터 중복 조회시 한 번만 DB에 전달
  생산성  반복되는 SQL 작성과 JDBC API 사용 대신 처리
  유지보수  엔티티 변경에 대한 수정 코드 작성량 감소
  패러다임 불일치 해결  상속, 연관관계, 객체 그래프 탐색, 비교 문제 해결
  데이터 접근 추상화와 벤더 독립성  특정 DB 기술 종속 X (DB Dialect 설정) 

- 단점 : 학습 곡선 매우 높음 (객체와 관계형 데이터베이스의 상위)


'Development > JPA' 카테고리의 다른 글

엔티티 매핑  (0) 2017.11.12
영속성 관리  (0) 2017.01.21
JPA 시작  (0) 2016.11.20

+ Recent posts