영권's

TIL - JPA 본문

데브코스 웹 백엔드/TIL

TIL - JPA

ykkkk 2021. 9. 28. 04:24

2021-09-27 TIL

 

기존에 java 어플리케이션과 RDB가 통신하기 위해서 JDBC, JDBCTemplate, Mybatis 를 많이 이용했었는데 이 방법들은 RDB와 자바 객체가 가지는 기본적인 패러다임의 불일치가 발생하게 되고 이를 JPA로 극복할 수 있다.

 

예를 들어 JDBC, JDBCTemplate의 경우 자바 코드에 쿼리문이 삽입 되어 있는 한계점이 있고 Mybatis 또한 자바 객체와 테이블간의 동일성을 유지하기가 어려울 수 있다.

jpa가 ORM(Object Relation Mapper)인 이유도 객체와 RDB간의 관계를 매핑 시켜주기 때문인데 

 

jpa를 사용 했을 때 장점

  1. 생산성 증진
    • Mybatis를 이용하면 만약 객체에 필드가 추가되거나 하면 쿼리를 수정하거나 해야하는데 이를 SQL의존적인 개발을 한다라고 하는데 여기에서 탈피 할 수 있고, 객체 중심으로 생산적인 개발이 가능하다.
  2. 객체와 관계형 테이블의 패러다임 불일치
    • 객체지향 프로그래밍은 추상화, 캡슐화, 다형성, 상속 등을 제공한다.
    • RDB는 데이터 중심으로 구조화 되어 있고 OOP의 특징을 지원하지 않기 때문에 패러다임 불일치라는 문제점이 생기게 되는데 jpa를 사용하면 이를 해결할 수 있다.

 

예시)

@Entity
@Table(name = "customers")
public class Customer {
    @Id
    private Long id;
    private String firstName;
    private String lastName;

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
@Repository
public interface CustomerRepository extends JpaRepository<Customer,Long> {

}

고객을 뜻하는 도메인인 Customer 클래스를 만들고 해당 레포지토리를 만들면 sql 작성없이 save, findAll 등의 메서드를 사용할 수 있다.

그리고 만약 Customer 클래스에서 age 필드를 추가해도 sql의 수정없이 똑같이 CRUD 관련한 메서드를 사용할 수 있다.

 

만약 Mybatis를 사용했다면 먼저 rdb의 테이블과 Customer클래스를 매핑해주기 위한 설정과 각각의 쿼리를 작성하고 age 필드를 추가하면 해당하는 쿼리를 모두 수정해줘야 하는 불편함이 있는데 이것을 해결할 수 있다.

 

jpa의 update는 @Transaction을 사용하는 방법이 있는데 메서드가 시작할 때 트랜잭션이 열려서 메서드가 끝날 때 커밋을 하게된다.

@Test
@Transactional
void updateTest(){
        // GIVEN
        Customer customer = new Customer();
        customer.setId(1L);
        customer.setFirstName("0kwon");
        customer.setLastName("choi");
        repository.save(customer);

        // WHEN
        Customer entity = repository.findById(1L).get();
        entity.setLastName("c");
        entity.setFirstName("yk");

        // THEN
        Customer updatedEntity = repository.findById(1L).get();
        log.info("{} {}", updatedEntity.getFirstName(), updatedEntity.getLastName());
    }

 

 

이 때 중간에 entity가 변경되었는지에 대한 Dirty Checking을 하고 JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해줍니다.

Comments