Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
JPA 잘 (하는 척) 하기
SLiPP-JPA 이경원
목차
● JPA 소개
● JDBC부터 JPA까지
● 객체와 테이블
● 엔티티 생명주기
● 영속성 컨텍스트
● Spring Data JPA
● 참고 자료
● QnA
JPA(Java Persistence API) 소개
● Java ORM(Object-Relational Mapping) 표준 F/W
● RDB를 객체로 표현(매핑), 사용
● Hibernate, Eclipse Link, TopLink Essensials 구현체
JDBC부터 JPA까지
요구 사항
단순 CRU(입력, 조회, 수정)
public class User {
private int userId;
private String name;
private String password;
}
JDBC
// connection…
1. 쿼리 생성
String insertQuery = "insert into User(userId, name, password) values(?, ?, ?)";
2. parameter 매핑
p...
// connection…
1. 쿼리 생성
String selectQuery = "select userId, name, password from User where userId =" +
user.getUserId();
...
// connection…
1. 쿼리 생성
String updateQuery = "update User set name = ?, password = ? where userId = ?";
2. parameter 매핑
ps...
Query 생성, 실행, 데이터 매핑 반복
Connection, close 코드 반복
MyBatis
1. insert
<insert id="inser" parameterType="User">
insert into User(userId, name, password) values (#{userId}, #{name}, #{...
Connection, close 위임
parameter 매핑, 데이터 매핑 위임
하지만 여전히 Query 작성 반복
JPA
EntityManager em = entityManagerFactory.createEntityManager();
// Insert
em.persist(user);
// Select
User user = em.find(U...
Connection, close 위임
쿼리 자동 생성, 실행
User 테이블에
“nickName” 컬럼이 추가 된다면?
public class User {
private int userId;
private String name;
private String password;
// nickName 컬럼 추가
private String nic...
JDBC
1. insert 쿼리 생성
String insertQuery = "insert into User(userId, name, password, nickName) values(?, ?, ?, ?)";
2. parameter...
1. select 쿼리 생성
String selectQuery = "select userId, name, password, nickname from User where userId = " +
user.getUserId(...
1. update 쿼리 생성
String updateQuery = "update User set name = ?, password = ?, nickName = ? where userId =
?";
2. parameter...
Query 수정, 데이터 매핑 코드 추가
MyBatis
1. insert
<insert id="inser" parameterType="User">
insert into User(userId, name, password, nickName)
values (#{userId}, #...
Query 수정
JPA는 얼마나 변경됐을까요?
// insert
em.persist(user);
// select
em.find(User.class, user.getUserId());
// update
user.setName("update Name");
user.s...
모든 Domain은 변경된다.
● type safe 하지 않고
● 실수할 확률이 높고
● 수정해야 할 코드가 많아지며
● 단순 CRUD 코드를 반복한다.
객체와 테이블
테이블 지향 엔티티
public class User {
private int userId;
private String name;
private String password;
private String nickName;
...
객체 지향 엔티티
public class User {
private int userId;
private String name;
private String password;
private String nickName;
}...
● 객체 그래프 탐색
● 테이블과 객체 간 연관 관계 불일치
● Query 작성 증가
엔티티 생명주기
● New(비영속) : DB에 반영 되지 않고 영속성 컨텍스트와 관
계 없는 엔티티
● Managed(영속) : 영속성 컨텍스트에 저장된 엔티티
● Detached(준영속) : 영속성 컨텍스트에서 분리된 엔티티
● Re...
비영속 그리고 준영속
// 비 영속
User newUser = new User(“name”, “password”, “nickName”);
// 준 영속
User detachUser = new User(1, “name”, “password”,...
detachUser.userId가
DB에 있는 경우 “준영속”
영속성 컨텍스트
● 쓰기 지연 SQL
● 자동 변경 감지
● 1차 캐시
● 엔티티 동일성
● 지연 로딩
영속성 컨텍스트는 어떻게 동작할까?
@Entity
@Table(name = "User")
public class User {
@Id @GeneratedValue
private Integer userId;
@Column(name = "name", nulla...
입력(persist)
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 비 영속 상태
User user = new User("wons", "12345"...
조회(find)
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 영속 엔티티
// 1차 캐시 저장
User user = em.find(User....
수정(자동 변경 감지)
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 영속 상태
// 1차 캐시 저장
User user = em.find(User.c...
삭제(remove)
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 영속 상태, 1차 캐시 저장
User user = em.find(User.cla...
지금까지 모든 일은 트랜젝션
작업 단위에서 동작
사실 commit은
EntityManager.flush()를 먼저 호출
flush()는 영속성 컨텍스트와 DB를 동기화
merge
준 영속 엔티티 -> 영속 엔티티
merge를 알아보기 전에
영속 엔티티 -> 준 영속 엔티티
● em.clear();
● em.detach(user);
● em.getTransaction().commit();
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 1. 영속 상태
User user1 = em.find(User.class, 1)...
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 5. name 속성 값은?
User user2 = em.find(User.cla...
● 속성이 변경된 준영속 엔티티 merge : update
● 비영속 엔티티 merge : insert
즉 merge는 영속 엔티티로 만들기도 하지
만
update 또는 insert 하기도 함
준 영속 상태는 영속성 컨텍스트
특징을 사용하지 못하는 것
● 쓰기 지연 SQL
● 자동 변경 감지
● 1차 캐시
● 엔티티 동일성
● 지연 로딩
Spring Data JPA
소개 정도만 할게요.
@Entity
@Table(name = "User")
public class User {
@Id @GeneratedValue
private Integer userId;
@Column(name = "name", nulla...
Repository Interface
public interface UserRepository extends JpaRepository<User, Integer> {
}
Repository 만 추가 하면
● save(T);
● delete(T);
● findOne(ID);
● findAll();
● findAll(Pageable);
CRUD 그 외 조회 Query가
필요하다면?
Query Method
http://goo.gl/luWvvP
method 이름으로 Query생성
정확히 말하면 JPQL 생성
물론 규칙을 지켜 method 이름 설정
public interface UserRepository extends JpaRepository<User, Integer> {
// where u.name = ?name
User findByName(String name...
참고자료
● http://www.tutorialspoint.com/jpa/
● http://www.objectdb.com/
● https://en.wikibooks.
org/wiki/Java_Persistence
● http://goo.gl/xzpTdK
● https://goo.gl/sqmO9p
● https://goo.gl/GhsI4Q
● https://goo.gl/GpQzeL
QnA
● blog : http://blog.woniper.net
● github : https://github.com/woniper
● email : leekw3747@gmail.com
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
Upcoming SlideShare
Loading in …5
×

Jpa 잘 (하는 척) 하기

28,930 views

Published on

SLiPP 스터디 JPA 발표. 2015.09.23(수)
참고 : https://github.com/woniper/SLiPP-JPA-Study

Published in: Technology

Jpa 잘 (하는 척) 하기

  1. 1. JPA 잘 (하는 척) 하기 SLiPP-JPA 이경원
  2. 2. 목차 ● JPA 소개 ● JDBC부터 JPA까지 ● 객체와 테이블 ● 엔티티 생명주기 ● 영속성 컨텍스트 ● Spring Data JPA ● 참고 자료 ● QnA
  3. 3. JPA(Java Persistence API) 소개
  4. 4. ● Java ORM(Object-Relational Mapping) 표준 F/W ● RDB를 객체로 표현(매핑), 사용 ● Hibernate, Eclipse Link, TopLink Essensials 구현체
  5. 5. JDBC부터 JPA까지
  6. 6. 요구 사항
  7. 7. 단순 CRU(입력, 조회, 수정) public class User { private int userId; private String name; private String password; }
  8. 8. JDBC
  9. 9. // 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...
  10. 10. // 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...
  11. 11. // 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...
  12. 12. Query 생성, 실행, 데이터 매핑 반복
  13. 13. Connection, close 코드 반복
  14. 14. MyBatis
  15. 15. 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>
  16. 16. Connection, close 위임 parameter 매핑, 데이터 매핑 위임
  17. 17. 하지만 여전히 Query 작성 반복
  18. 18. JPA
  19. 19. EntityManager em = entityManagerFactory.createEntityManager(); // Insert em.persist(user); // Select User user = em.find(User.class, user.getUserId()); // Update user.setName("update Name"); user.setPassword("1111"); // Delete em.remove(user);
  20. 20. Connection, close 위임 쿼리 자동 생성, 실행
  21. 21. User 테이블에 “nickName” 컬럼이 추가 된다면?
  22. 22. public class User { private int userId; private String name; private String password; // nickName 컬럼 추가 private String nickName; }
  23. 23. JDBC
  24. 24. 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);
  25. 25. 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"));
  26. 26. 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);
  27. 27. Query 수정, 데이터 매핑 코드 추가
  28. 28. MyBatis
  29. 29. 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>
  30. 30. Query 수정
  31. 31. JPA는 얼마나 변경됐을까요?
  32. 32. // insert em.persist(user); // select em.find(User.class, user.getUserId()); // update user.setName("update Name"); user.setPassword("1111"); // delete em.remove(user); // insert em.persist(user); // select em.find(User.class, user.getUserId()); // update user.setName("update Name"); user.setPassword("1111"); user.setNickName("update nickName"); // delete em.remove(user); 요구사항 변경 전 요구사항 변경 후
  33. 33. 모든 Domain은 변경된다.
  34. 34. ● type safe 하지 않고 ● 실수할 확률이 높고 ● 수정해야 할 코드가 많아지며 ● 단순 CRUD 코드를 반복한다.
  35. 35. 객체와 테이블
  36. 36. 테이블 지향 엔티티 public class User { private int userId; private String name; private String password; private String nickName; } public class Board { private int boardId; // foreign key private int userId; private String title; private String content; }
  37. 37. 객체 지향 엔티티 public class User { private int userId; private String name; private String password; private String nickName; } public class Board { private int boardId; // object reference private User user; private String title; private String content; }
  38. 38. ● 객체 그래프 탐색 ● 테이블과 객체 간 연관 관계 불일치 ● Query 작성 증가
  39. 39. 엔티티 생명주기
  40. 40. ● New(비영속) : DB에 반영 되지 않고 영속성 컨텍스트와 관 계 없는 엔티티 ● Managed(영속) : 영속성 컨텍스트에 저장된 엔티티 ● Detached(준영속) : 영속성 컨텍스트에서 분리된 엔티티 ● Removed(삭제) : 삭제된 엔티티
  41. 41. 비영속 그리고 준영속
  42. 42. // 비 영속 User newUser = new User(“name”, “password”, “nickName”); // 준 영속 User detachUser = new User(1, “name”, “password”, “nickName”);
  43. 43. detachUser.userId가 DB에 있는 경우 “준영속”
  44. 44. 영속성 컨텍스트
  45. 45. ● 쓰기 지연 SQL ● 자동 변경 감지 ● 1차 캐시 ● 엔티티 동일성 ● 지연 로딩
  46. 46. 영속성 컨텍스트는 어떻게 동작할까?
  47. 47. @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; }
  48. 48. 입력(persist)
  49. 49. EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 비 영속 상태 User user = new User("wons", "12345", "woniper"); // 영속 상태 // 1차 캐시 저장 em.persist(user); // 준영속 상태 // SQL 저장소 쿼리 반영 em.getTransaction().commit(); em.close();
  50. 50. 조회(find)
  51. 51. EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 영속 엔티티 // 1차 캐시 저장 User user = em.find(User.class, user.getUserId()); // 준영속 상태 em.getTransaction().commit(); em.close();
  52. 52. 수정(자동 변경 감지)
  53. 53. 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();
  54. 54. 삭제(remove)
  55. 55. 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();
  56. 56. 지금까지 모든 일은 트랜젝션 작업 단위에서 동작
  57. 57. 사실 commit은 EntityManager.flush()를 먼저 호출
  58. 58. flush()는 영속성 컨텍스트와 DB를 동기화
  59. 59. merge
  60. 60. 준 영속 엔티티 -> 영속 엔티티
  61. 61. merge를 알아보기 전에
  62. 62. 영속 엔티티 -> 준 영속 엔티티
  63. 63. ● em.clear(); ● em.detach(user); ● em.getTransaction().commit();
  64. 64. 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();
  65. 65. EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 5. name 속성 값은? User user2 = em.find(User.class, 1); em.getTransaction().commit(); em.close();
  66. 66. ● 속성이 변경된 준영속 엔티티 merge : update ● 비영속 엔티티 merge : insert
  67. 67. 즉 merge는 영속 엔티티로 만들기도 하지 만 update 또는 insert 하기도 함
  68. 68. 준 영속 상태는 영속성 컨텍스트 특징을 사용하지 못하는 것
  69. 69. ● 쓰기 지연 SQL ● 자동 변경 감지 ● 1차 캐시 ● 엔티티 동일성 ● 지연 로딩
  70. 70. Spring Data JPA
  71. 71. 소개 정도만 할게요.
  72. 72. @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; }
  73. 73. Repository Interface
  74. 74. public interface UserRepository extends JpaRepository<User, Integer> { }
  75. 75. Repository 만 추가 하면
  76. 76. ● save(T); ● delete(T); ● findOne(ID); ● findAll(); ● findAll(Pageable);
  77. 77. CRUD 그 외 조회 Query가 필요하다면?
  78. 78. Query Method http://goo.gl/luWvvP
  79. 79. method 이름으로 Query생성
  80. 80. 정확히 말하면 JPQL 생성
  81. 81. 물론 규칙을 지켜 method 이름 설정
  82. 82. public interface UserRepository extends JpaRepository<User, Integer> { // where u.name = ?name User findByName(String name); // where u.name = ?name and u.password = ?password; User findByNameAndPassword(String name, String password); }
  83. 83. 참고자료
  84. 84. ● http://www.tutorialspoint.com/jpa/ ● http://www.objectdb.com/ ● https://en.wikibooks. org/wiki/Java_Persistence
  85. 85. ● http://goo.gl/xzpTdK ● https://goo.gl/sqmO9p ● https://goo.gl/GhsI4Q ● https://goo.gl/GpQzeL
  86. 86. QnA
  87. 87. ● blog : http://blog.woniper.net ● github : https://github.com/woniper ● email : leekw3747@gmail.com

×