프로필사진

Go, Vantage point

가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.


Github | https://github.com/overnew/

Blog | https://everenew.tistory.com/





티스토리 뷰

개발/Spring DataBase

[Spring DB] 9. JPA

EVEerNew 2022. 7. 27. 17:28
반응형

 

 

 

* 김영한님의 스프링 DB 2편 강좌를 수강하며 정리한 글입니다. *

 

스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의 소개 | 인

www.inflearn.com

 

 

 

이전 글에서는 MyBatis에 대해 정리하였다.

 

 

JPA(Java Persistence API)

 

JdbcTemplate와 MyBatis는 SQLMapper로 결국에는 SQL을 작성해야 한다.

 

DB에 맞는 SQL문도 자동으로 작성해 주는 것이 ORM 기술(Obiect-relational mapping)이다.

ORM은 객체를 관계형 데이터와 매핑하는 역할을 한다.

대표적인 ORM 기술이 JPA로 스프링 + JPA의 조합은 국내외로 굉장히 많이 사용한다.

 

실무에서는 스프링 데이터 JPA와 Querydsl을 이용하여 JPA를 편리하게 사용한다.

 

 

관계형 데이터베이스는 SQL을 반복적으로 사용해야 한다.

특히 모든 데이터 객체의 CRUD 기능마다 SQL이 필요하다.

 

객체지향의 관점에서 SQL 중심 개발의 문제점을 생각해보자.

객체를 관계형 DB에 넣기 위해서는 SQL로 변환해야 한다. 이 작업이 개발자가 해야 하는 SQLMapper 작업이다.

거기에 SQL에는 상속관계가 존재하지 않는다. 억지로 만들어보아도 적절한 Join 구문을 매번 이용하는 것은 만만치 않다.

만약 데이터를 꺼내와 인스턴스에 담는다면, 같은 값을 꺼내온 인스턴스들이라도 다른 인스턴스로 인식될 수 있다.

우리는 자바 컬렉션에 저장하듯이 객체를 넣고 빼고 싶다.

 

 

 

이를 위해 사용하는 것이 JPA(Java Persistence API), 자바의 ORM기술 표준이다.

JPA를 이용하면 DB의 데이터를 마치 자바의 컬랙션의 조회처럼 사용할 수 있다.

 

find(by ID) 메서드를 호출하면 JPA 가 SQL(SELECT)을 생성하고 DB의 API를 이용해 쿼리를 진행한다.

DB로부터 반환된 Result Set을 객체로 매핑시켜 인스턴스를 반환하므로, 호출자 입장에서는 컬렉션에서 인스턴스를 꺼내온 것과 동일하다.

 

JPA는 이름에서도 알 수 있듯이 인터페이스이고 이를 구현한 구현체가 하이버네이트이다.

 

 

 

생산성 증가

 

JPA는 CRUD기능 제공하여 생산성이 올라간다.

저장: jpa.persist(object)

조회: Object ob = jpa.find(object_id)

수정: object.setName("이름쓰")

삭제: jpa.remove(object)

 

CRUD를 위한 SQL 구문은 JPA가 자동으로 생성해 주므로 객체의 필드를 수정으로 인해, SQL도 수정할 필요가 없어진다.

상속 관계의 데이터도 자동으로 조회할 수 있는 SQL로 처리해준다.

 

 

 

성능의 향상

 

JPA 같은 데이터를 조회해 반환된 인스턴스는 같은 인스턴스로 보장해준다.(같은 트랜잭션 내에서)

이런 방식은 1차 캐시를 통해 제공된다.

새로운 인스턴스의 생성을 방지하기 때문에 성능 향상에도 도움이 된다.

 

거기에 쓰기 지연을 통해, INSERT를 위한 데이터를 버퍼처럼 모아두었다가 commit시에 한 번에 전송시킨다.

이외에도 지연 로딩과 즉시 로딩을 지원한다.

 

 

 

JPA 적용

 

JPA의 가장 중요한 부분이 DB table과  객체의 매핑을 하는 ORM(Obiect-relational mapping) 과정이다.

 

@Entity	//JPA의 인식을 위해 필요
@Table (name = "item") //객체 명과 같으면 생략가능
public class Item {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) //pk값이 db에서 자동 넣어 주는 것으로 설정
    private Long id;

    @Column(name = "item_name", length = 10)
    private String itemName;
    private Integer price;  //컬럼 명이 변수와 같으면 생략가능
    private Integer quantity;
    
    public Item() { //기본 생성자 필수
    }
    
    ...
 }

table과의 맵핑을 위해서 해당 객체에 @Entity를 붙여주어야 한다.

 

@Id는 테이블의 Primary Key를 매핑시킨다.

@GeneratedValue(strategy = GenerationType.IDENTITY)으로 DB가 자동 생성해주는 값으로 설정해준다.

 

@Table 어노테이션은 테이블이 객체의 명과 같다면 생략 가능하다

동일하게 @Column도 컬럼이 필드 변수 명과 같다면 생략 가능하다.

(cemel case <-> 언더 스코어 case 자동 변환)

 

이런 설정은 ENTITY INSERT 쿼리도 생성하지만, 테이블 생성도 가능하다. 

 

단, JPA는 public 또는 protect 기본 생성자를 필수로 한다.

 

@Transactional //JPA는 모두 같은 트랜잭션에서 이뤄지도록해야함
public class JpaItemRepository implements ItemRepository {

    private final EntityManager em; //JPA의 필수, datasource등의 복잡한 과정을 자동으로로
	
    @Override
    public Item save(Item item) {
        em.persist(item);   //객체의 매핑정보로 자동 SQL 쿼리 생성, 전송
        return item;
    }

    @Override
    public void update(Long itemId, ItemUpdateDto updateParam) {
        Item findItem = em.find(Item.class, itemId);//일단 찾고
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
        //마치 실제 인스턴스 처럼 update가능, JPA가 자동으로 update 쿼리가 나간다.
        // 트랜잭션의 commit 시점에 DB에 UPDATE 쿼리를 날림
    }
    
    ...
}

 

JPA를 사용하기 위해서는 두 가지가 필요하다.

 

EntityManger 를 주입받아 JPA를 사용한다.

EntityManger는 dataSource를 가지고 있기 때문에 DB로 접근할 수 있다.

 

@Transactional

JPA의 데이터 변경 작업은 같은 트랜잭션 안에서 이뤄 저야 하므로 @Transactional 어노테이션을 적용해주자.

 

 

이제 EntityManger의 메서드를 사용하면 마치 자바 컬렉션처럼 편리하게 인스턴스를 DB에 넣고 뺄 수 있게 된다.

 

 

JPA가 만드는 save() 메서드의 sql로그를 확인해보면 정상적으로 동작함을 확인할 수 있다.

 

 

단순히 PK가 아닌 값들로 조회하기 위해서는 JPQL을 사용한다.

JPA 전용 QL을 사용해도 동적 쿼리가 불편한데, Querydsl을 활용하면 깔끔하게 해결된다.

 

 

 

JPA 예외

 

JPA는 스프링과는 독립적인 기술로 EntityManger는 JPA 관련 예외를 발생시킨다.

JPA는 데이터 계층 기술인데, 이곳의 예외가 처리되지 않아 서비스 계층으로 넘어가면 서비스 계층이 JPA를 의존해야 한다.

여기서도 사용되는 것이 스프링의 예외 변환기이다.

 

 

@Repository는 컴포넌트 스캔의 대상이 되고, 예외 변환 AOP의 적용대상이 된다.

스프링은 JPA 예외 변환기를 등록하고, 예외 발생 시 예외 변환 AOP Proxy가 스프링 예외 추상화로 바꾸어 넘긴다.

 

 

반응형
댓글
반응형
인기글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함