woniper

[JPA] JPA란 무엇인가? 본문

Framework

[JPA] JPA란 무엇인가?

woniper1 2015. 5. 1. 15:22
  1. JPA란 무엇인가?
  2. JavaSE 환경에서 JPA 설정 및 CRUD
  3. JavaEE 환경(Spring)에서 JPA 설정 및 CRUD
  4. @OneToOne, 1:1 관계 매핑
  5. @OneToMany / @ManyToOne, 1:N / N:1 관계 매핑
  6. @ManyToMany, N:M 관계 매핑
  7. Entity 객체 생명주기(Lifecycle)와 Persistence Context

JPA(Java Persistent API)

  JPA는 여러 ORM 전문가가 참여한 EJB 3.0 스펙 작업에서 기존 EJB ORM이던 Entity Bean을 JPA라고 바꾸고 JavaSE, JavaEE를 위한 영속성(persistence) 관리와 ORM을 위한 표준 기술이다. JPA는 ORM 표준 기술로 Hibernate, OpenJPA, EclipseLink, TopLink Essentials과 같은 구현체가 있고 이에 표준 인터페이스가 바로 JPA이다.

  ORM(Object Relational Mapping)이란 RDB 테이블을 객체지향적으로 사용하기 위한 기술이다. RDB 테이블은 객체지향적 특징(상속, 다형성, 레퍼런스, 오브젝트 등)이 없고 자바와 같은 언어로 접근하기 쉽지 않다. 때문에 ORM을 사용해 오브젝트와 RDB 사이에 존재하는 개념과 접근을 객체지향적으로 다루기 위한 기술이다.


장점

  • 객체지향적으로 데이터를 관리할 수 있기 때문에 비즈니스 로직에 집중 할 수 있으며, 객체지향 개발이 가능하다.
  • 테이블 생성, 변경, 관리가 쉽다. (JPA를 잘 이해하고 있는 경우)
  • 로직을 쿼리에 집중하기 보다는 객체자체에 집중 할 수 있다.
  • 빠른 개발이 가능하다.

단점

  • 어렵다. 장점을 더 극대화 하기 위해서 알아야 할게 많다.
  • 잘 이해하고 사용하지 않으면 데이터 손실이 있을 수 있다. (persistence context)
  • 성능상 문제가 있을 수 있다.(이 문제 또한 잘 이해해야 해결이 가능하다.)

왜 ORM 인가?
  보통 한국은 xBatis를 현업에서 대부분 사용하는데, 쿼리 자체에 집중하고 비즈니스 로직을 쿼리에 의존하게 되면 객체지향의 장점을 놓칠 수 있는 가능성이 크다. 예를 들어 아래와 같은 User 테이블과 Order 테이블이 있다.

크게 복잡하지 않은 1(user):N(order) 관계의 테이블이다. 

즉 한명의 user는 여러 order를 가질 수 있고 order는 fk로 user_id를 가지고 있다.

보통 쿼리를 이용해서 이 테이블을 객체로 만들때는

public class User {
    private int userId;
    private String username;
    private String nickName;
    private String address;
}

public class Order {
    private int orderId;
    private String orderName;
    private String note;
    private int userId;
}

이런식의 DTO 또는 VO 클래스를 만드는데 User가 자신이 생성한 Order 데이터를 가져오기 위해서는 

select * from tbl_user u join tbl_order o on u.user_id = o.user_id
where u.user_id = #{value}
또는
select * from tbl_order where user_id = #{value}

이렇게 쿼리가 작성 된다. 여기서 주의해서 봐야될 부분은 바로 Order 클래스에 userId 변수다. 이 변수는 order를 생성한 User의 id를 가지고 있다. 즉 테이블 관점으로 본다면 userId 변수는 fk가 되는 것이다. User 객체가 아니라 User의 pk만 가지고 있는 것이다.

그럼, ORM에서는 객체를 어떻게 구성할까? (Annotation은 JPA Annotation이다. 아직 이해 못해도 상관없다.)

@Entity(name = "tbl_user")
public class User {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer userId;
    private String username;
    private String nickName;
    private String address;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Order> orders;
}

@Entity(name = "tbl_order")
public class Order {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer orderId;
    private String orderName;
    private String note;
    private int price;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;
}

  User 객체는 Order List 객체를, Order 객체는 User 객체를 가지고 있다. 테이블 관점으로 보나, 객체 관점으로 보나 pk, fk도 만족을 하며, 객체지향적으로 객체를 만든 것이다. 심지어 데이터를 조작하기 위한 쿼리 자체도 신경쓰지 않는다. 쿼리 자체를 신경쓰지 않는다는 뜻은 다음 포스팅에서 설명하겠지만 실제 User 객체나 Order 객체를 테이블에서 조회해서 만드는 과정에 있어 위 예제와 같이 쿼리를 작성해서 만들지 않는다는 뜻이다.(내부적으로는 쿼리가 실행되고 실제로 우리는 그 쿼리가 어떻게 만들어지고 실행되는지 정확히 인지하고 있어야 정확한 JPA 사용이 가능하다.) 우리가 쿼리를 작성하지 않는다는 뜻이지 쿼리가 실제로 실행 안된다는 뜻은 아니다.

  이렇게 객체지향적인 객체가 생성되면 우린 비즈니스 로직 자체를 쿼리에 집중하지 않고 자바 코드 자체에 집중 할 수 있다는 것이다. 코드에 비즈니스 로직을 집중할 수 있다는 것은 많은 장점이 있는데 유지보수, 테스트, 디버깅, 객체지향과 같은 여러 장점을 갖을 수 있다.

물론 xBatis나 JDBC, Spring JDBC Template과 같은 쿼리를 작성하는 기술을 사용해도 객체지향적인 객체 설계가 가능하지만 좀 더 쉽고 빠르게 쓸 수 있는 것이 ORM이다.


참고 자료


Comments