jpa 잘 (하는 척) 하기

101
JPA (하는 ) 하기 SLiPP-JPA 이경원

Upload: -

Post on 15-Apr-2017

11.723 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Jpa 잘 (하는 척) 하기

JPA 잘 (하는 척) 하기

SLiPP-JPA 이경원

Page 2: Jpa 잘 (하는 척) 하기

목차

● JPA 소개

● JDBC부터 JPA까지

● 객체와 테이블

● 엔티티 생명주기

● 영속성 컨텍스트

● Spring Data JPA

● 참고 자료

● QnA

Page 3: Jpa 잘 (하는 척) 하기

JPA(Java Persistence API) 소개

Page 4: Jpa 잘 (하는 척) 하기

● Java ORM(Object-Relational Mapping) 표준 F/W

● RDB를 객체로 표현(매핑), 사용

● Hibernate, Eclipse Link, TopLink Essensials 구현체

Page 5: Jpa 잘 (하는 척) 하기

JDBC부터 JPA까지

Page 6: Jpa 잘 (하는 척) 하기

요구 사항

Page 7: Jpa 잘 (하는 척) 하기

단순 CRU(입력, 조회, 수정)

public class User {

private int userId;

private String name;

private String password;

}

Page 8: Jpa 잘 (하는 척) 하기

JDBC

Page 9: Jpa 잘 (하는 척) 하기

// connection…

1. 쿼리 생성String insertQuery = "insert into User(userId, name, password) values(?, ?, ?)";

2. parameter 매핑pstmt.setInt(1, user.getUserId());pstmt.setString(2, user.getName());pstmt.setString(3, user.getPassword());

3. 쿼리 실행pstmt.executeUpdate(insertQuery);

// close...

Page 10: Jpa 잘 (하는 척) 하기

// connection…

1. 쿼리 생성String selectQuery = "select userId, name, password from User where userId =" +

user.getUserId();

2. 쿼리 실행ResultSet rs = stmt.executeQuery(selectQuery);

3. 데이터 매핑user.setUserId(rs.getInt("userId"));user.setName(rs.getString("name"));user.setPassword(rs.getString("password"));

// close...

Page 11: Jpa 잘 (하는 척) 하기

// connection…

1. 쿼리 생성String updateQuery = "update User set name = ?, password = ? where userId = ?";

2. parameter 매핑pstmt.setString(1, user.getName());pstmt.setString(2, user.getPassword());pstmt.setInt(3, user.getUserId());

3. 쿼리 실행pstmt.executeUpdate(updateQuery);

// close...

Page 12: Jpa 잘 (하는 척) 하기

Query 생성, 실행, 데이터 매핑 반복

Page 13: Jpa 잘 (하는 척) 하기

Connection, close 코드 반복

Page 14: Jpa 잘 (하는 척) 하기

MyBatis

Page 15: Jpa 잘 (하는 척) 하기

1. insert<insert id="inser" parameterType="User">

insert into User(userId, name, password) values (#{userId}, #{name}, #{password})</insert>

2. select<select id="select" parameterType="java.lang.Integer" resultType="User">

select userId, name, password from User where userId = #{userId}</select>

3. update<update id="update" parameterType="User">

update User set name = #{name}, password = #{password} where userId = #{userId}</update>

Page 16: Jpa 잘 (하는 척) 하기

Connection, close 위임

parameter 매핑, 데이터 매핑 위임

Page 17: Jpa 잘 (하는 척) 하기

하지만 여전히 Query 작성 반복

Page 18: Jpa 잘 (하는 척) 하기

JPA

Page 19: Jpa 잘 (하는 척) 하기

EntityManager em = entityManagerFactory.createEntityManager();

// Insertem.persist(user);

// SelectUser user = em.find(User.class, user.getUserId());

// Updateuser.setName("update Name");user.setPassword("1111");

// Deleteem.remove(user);

Page 20: Jpa 잘 (하는 척) 하기

Connection, close 위임

쿼리 자동 생성, 실행

Page 21: Jpa 잘 (하는 척) 하기

User 테이블에

“nickName” 컬럼이 추가 된다면?

Page 22: Jpa 잘 (하는 척) 하기

public class User {

private int userId;

private String name;

private String password;

// nickName 컬럼 추가private String nickName;

}

Page 23: Jpa 잘 (하는 척) 하기

JDBC

Page 24: Jpa 잘 (하는 척) 하기

1. insert 쿼리 생성String insertQuery = "insert into User(userId, name, password, nickName) values(?, ?, ?, ?)";

2. parameter 매핑pstmt.setInt(1, user.getUserId());pstmt.setString(2, user.getName());pstmt.setString(3, user.getPassword());pstmt.setString(4, user.getNickName());

3. 쿼리 실행pstmt.executeUpdate(insertQuery);

Page 25: Jpa 잘 (하는 척) 하기

1. select 쿼리 생성String selectQuery = "select userId, name, password, nickname from User where userId = " +

user.getUserId();

2. 쿼리 실행ResultSet rs = stmt.executeQuery(selectQuery);

3. 데이터 매핑user.setUserId(rs.getInt("userId"));user.setName(rs.getString("name"));user.setPassword(rs.getString("password"));user.setNickName(rs.getString("nickName"));

Page 26: Jpa 잘 (하는 척) 하기

1. update 쿼리 생성String updateQuery = "update User set name = ?, password = ?, nickName = ? where userId = ?";

2. parameter 매핑pstmt.setString(1, user.getName());pstmt.setString(2, user.getPassword());pstmt.setString(3, user.getNickName());pstmt.setInt(4, user.getUserId());

3. 쿼리 실행pstmt.executeUpdate(updateQuery);

Page 27: Jpa 잘 (하는 척) 하기

Query 수정, 데이터 매핑 코드 추가

Page 28: Jpa 잘 (하는 척) 하기

MyBatis

Page 29: Jpa 잘 (하는 척) 하기

1. insert<insert id="inser" parameterType="User">

insert into User(userId, name, password, nickName) values (#{userId}, #{name}, #{password}, #{nickName})

</insert>

2. select<select id="select" parameterType="java.lang.Integer" resultType="User">

select userId, name, password, nickName from User where userId = #{userId}</select>

3. update<update id="update" parameterType="User">

update User set name = #{name}, password = #{password}, nickName = #{nickName} where userId = #{userId}

</update>

Page 30: Jpa 잘 (하는 척) 하기

Query 수정

Page 31: Jpa 잘 (하는 척) 하기

JPA는 얼마나 변경됐을까요?

Page 32: Jpa 잘 (하는 척) 하기

// insertem.persist(user);

// selectem.find(User.class, user.getUserId());

// updateuser.setName("update Name");user.setPassword("1111");

// deleteem.remove(user);

// insertem.persist(user);

// selectem.find(User.class, user.getUserId());

// updateuser.setName("update Name");user.setPassword("1111");user.setNickName("update nickName");

// deleteem.remove(user);

요구사항 변경 전 요구사항 변경 후

Page 33: Jpa 잘 (하는 척) 하기

모든 Domain은 변경된다.

Page 34: Jpa 잘 (하는 척) 하기

● type safe 하지 않고

● 실수할 확률이 높고

● 수정해야 할 코드가 많아지며

● 단순 CRUD 코드를 반복한다.

Page 35: Jpa 잘 (하는 척) 하기

객체와 테이블

Page 36: Jpa 잘 (하는 척) 하기

테이블 지향 엔티티public class User {

private int userId;

private String name;

private String password;

private String nickName;

}

public class Board {

private int boardId;

// foreign keyprivate int userId;

private String title;

private String content;

}

Page 37: Jpa 잘 (하는 척) 하기

객체 지향 엔티티public class User {

private int userId;

private String name;

private String password;

private String nickName;

}

public class Board {

private int boardId;

// object referenceprivate User user;

private String title;

private String content;

}

Page 38: Jpa 잘 (하는 척) 하기

● 객체 그래프 탐색

● 테이블과 객체 간 연관 관계 불일치

● Query 작성 증가

Page 39: Jpa 잘 (하는 척) 하기

엔티티 생명주기

Page 40: Jpa 잘 (하는 척) 하기

● New(비영속) : DB에 반영 되지 않고 영속성 컨텍스트와 관

계 없는 엔티티

● Managed(영속) : 영속성 컨텍스트에 저장된 엔티티

● Detached(준영속) : 영속성 컨텍스트에서 분리된 엔티티

● Removed(삭제) : 삭제된 엔티티

Page 41: Jpa 잘 (하는 척) 하기
Page 42: Jpa 잘 (하는 척) 하기

비영속 그리고 준영속

Page 43: Jpa 잘 (하는 척) 하기

// 비 영속User newUser = new User(“name”, “password”, “nickName”);

// 준 영속User detachUser = new User(1, “name”, “password”, “nickName”);

Page 44: Jpa 잘 (하는 척) 하기

detachUser.userId가

DB에 있는 경우 “준영속”

Page 45: Jpa 잘 (하는 척) 하기

영속성 컨텍스트

Page 46: Jpa 잘 (하는 척) 하기

● 쓰기 지연 SQL

● 자동 변경 감지

● 1차 캐시

● 엔티티 동일성

● 지연 로딩

Page 47: Jpa 잘 (하는 척) 하기

영속성 컨텍스트는 어떻게 동작할까?

Page 48: Jpa 잘 (하는 척) 하기

@Entity@Table(name = "User")public class User {

@Id @GeneratedValueprivate Integer userId;

@Column(name = "name", nullable = true)private String name;

@Column(name = "password", nullable = true)private String password;

@Column(name = "nickName", nullable = true)private String nickName;

}

Page 49: Jpa 잘 (하는 척) 하기

입력(persist)

Page 50: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 비 영속 상태User user = new User("wons", "12345", "woniper");

// 영속 상태 // 1차 캐시 저장em.persist(user);

// 준영속 상태// SQL 저장소 쿼리 반영em.getTransaction().commit();em.close();

Page 51: Jpa 잘 (하는 척) 하기
Page 52: Jpa 잘 (하는 척) 하기
Page 53: Jpa 잘 (하는 척) 하기
Page 54: Jpa 잘 (하는 척) 하기

조회(find)

Page 55: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 영속 엔티티// 1차 캐시 저장User user = em.find(User.class, user.getUserId());

// 준영속 상태em.getTransaction().commit();em.close();

Page 56: Jpa 잘 (하는 척) 하기
Page 57: Jpa 잘 (하는 척) 하기
Page 58: Jpa 잘 (하는 척) 하기
Page 59: Jpa 잘 (하는 척) 하기

수정(자동 변경 감지)

Page 60: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 영속 상태// 1차 캐시 저장User user = em.find(User.class, user.getUserId());

// 자동 변경 감지user.setName("updateName");user.setPassword("1111");user.setNickName("updateNick");

// 준영속 상태// SQL 저장소 쿼리 반영em.getTransaction().commit();em.close();

Page 61: Jpa 잘 (하는 척) 하기
Page 62: Jpa 잘 (하는 척) 하기
Page 63: Jpa 잘 (하는 척) 하기
Page 64: Jpa 잘 (하는 척) 하기

삭제(remove)

Page 65: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 영속 상태, 1차 캐시 저장User user = em.find(User.class, user.getUserId());

// 삭제 상태em.remove(user);

// SQL 저장소 쿼리 반영em.getTransaction().commit();em.close();

Page 66: Jpa 잘 (하는 척) 하기
Page 67: Jpa 잘 (하는 척) 하기
Page 68: Jpa 잘 (하는 척) 하기
Page 69: Jpa 잘 (하는 척) 하기

지금까지 모든 일은 트랜젝션

작업 단위에서 동작

Page 70: Jpa 잘 (하는 척) 하기

사실 commit은

EntityManager.flush()를 먼저 호출

Page 71: Jpa 잘 (하는 척) 하기

flush()는 영속성 컨텍스트와 DB를 동기화

Page 72: Jpa 잘 (하는 척) 하기

merge

Page 73: Jpa 잘 (하는 척) 하기

준 영속 엔티티 -> 영속 엔티티

Page 74: Jpa 잘 (하는 척) 하기

merge를 알아보기 전에

Page 75: Jpa 잘 (하는 척) 하기

영속 엔티티 -> 준 영속 엔티티

Page 76: Jpa 잘 (하는 척) 하기

● em.clear();

● em.detach(user);

● em.getTransaction().commit();

Page 77: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 1. 영속 상태User user1 = em.find(User.class, 1);// 2. 준영속 상태em.detach(user1);// 3. name 속성 변경user1.setName("lee-kyung-won");// 4. 영속 상태em.merge(user1);

em.getTransaction().commit();em.close();

Page 78: Jpa 잘 (하는 척) 하기

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

// 5. name 속성 값은?User user2 = em.find(User.class, 1);

em.getTransaction().commit();em.close();

Page 79: Jpa 잘 (하는 척) 하기

● 속성이 변경된 준영속 엔티티 merge : update

● 비영속 엔티티 merge : insert

Page 80: Jpa 잘 (하는 척) 하기

즉 merge는 영속 엔티티로 만들기도 하지

update 또는 insert 하기도 함

Page 81: Jpa 잘 (하는 척) 하기

준 영속 상태는 영속성 컨텍스트

특징을 사용하지 못하는 것

Page 82: Jpa 잘 (하는 척) 하기

● 쓰기 지연 SQL

● 자동 변경 감지

● 1차 캐시

● 엔티티 동일성

● 지연 로딩

Page 83: Jpa 잘 (하는 척) 하기

Spring Data JPA

Page 84: Jpa 잘 (하는 척) 하기

소개 정도만 할게요.

Page 85: Jpa 잘 (하는 척) 하기

@Entity@Table(name = "User")public class User {

@Id @GeneratedValue private Integer userId;

@Column(name = "name", nullable = true) private String name;

@Column(name = "password", nullable = true) private String password;

@Column(name = "nickName", nullable = true) private String nickName;}

Page 86: Jpa 잘 (하는 척) 하기

Repository Interface

Page 87: Jpa 잘 (하는 척) 하기

public interface UserRepository extends JpaRepository<User, Integer> {}

Page 88: Jpa 잘 (하는 척) 하기

Repository 만 추가 하면

Page 89: Jpa 잘 (하는 척) 하기

● save(T);● delete(T);● findOne(ID);● findAll();● findAll(Pageable);

Page 90: Jpa 잘 (하는 척) 하기

CRUD 그 외 조회 Query가

필요하다면?

Page 91: Jpa 잘 (하는 척) 하기

Query Method

http://goo.gl/luWvvP

Page 92: Jpa 잘 (하는 척) 하기

method 이름으로 Query생성

Page 93: Jpa 잘 (하는 척) 하기

정확히 말하면 JPQL 생성

Page 94: Jpa 잘 (하는 척) 하기

물론 규칙을 지켜 method 이름 설정

Page 95: Jpa 잘 (하는 척) 하기

public interface UserRepository extends JpaRepository<User, Integer> {

// where u.name = ?nameUser findByName(String name);

// where u.name = ?name and u.password = ?password;User findByNameAndPassword(String name, String password);

}

Page 96: Jpa 잘 (하는 척) 하기

참고자료

Page 97: Jpa 잘 (하는 척) 하기
Page 99: Jpa 잘 (하는 척) 하기

● http://goo.gl/xzpTdK● https://goo.gl/sqmO9p● https://goo.gl/GhsI4Q● https://goo.gl/GpQzeL

Page 100: Jpa 잘 (하는 척) 하기

QnA

Page 101: Jpa 잘 (하는 척) 하기

● blog : http://blog.woniper.net

● github : https://github.com/woniper

● email : [email protected]