[Spring] 스프링 DB 2편 05

알재·2023년 12월 4일

스프링 DB

목록 보기
11/17

김영한님의 스프링 DB 2편 을 공부하여 정리한 글입니다.

JPA 설정

properties

#JPA log
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
  • org.hibernate.SQL=DEBUG : 하이버네이트가 생성하고 실행하는 SQL을 확인할 수 있다.
  • org.hibernate.type.descriptor.sql.BasicBinder=TRACE : SQL에 바인딩 되는 파라미터를 확인할 수 있다.

JPA 적용 - 개발

Item

@Data
@Entity
public class Item {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "item_name", length = 10)
    private String itemName;
    private Integer price;
    private Integer quantity;

    public Item() {
    }

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}
  • @Entity : JPA가 사용하는 객체라는 뜻이다. 이 에노테이션이 있어야 JPA가 인식할 수 있다.
    이렇게 @Entity 가 붙은 객체를 JPA에서는 엔티티라 한다.
  • @Id : 테이블의 PK와 해당 필드를 매핑한다.
  • @GeneratedValue(strategy = GenerationType.IDENTITY) :
    PK 생성 값을 데이터베이스에서 생성하는 IDENTITY 방식을 사용한다. 예) MySQL auto increment
  • @Column : 객체의 필드를 테이블의 컬럼과 매핑한다.
    @Column 을 생략할 경우 필드의 이름을 테이블 컬럼 이름으로 사용한다.
    참고로 지금처럼 스프링 부트와 통합해서 사용하면 필드 이름을 테이블 컬럼 명으로 변경할 때 객체 필드의 카멜 케이스를 테이블 컬럼의 언더스코어로 자동으로 변환해준다.
  • JPA는 public 또는 protected 의 기본 생성자가 필수이다.

Repository

@Slf4j
@Repository
@Transactional
public class JpaItemRepository implements ItemRepository {

    private final EntityManager em;

    public JpaItemRepository(EntityManager em) {
        this.em = em;
    }

    @Override
    public Item save(Item item) {
        em.persist(item);
        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());
    }

    @Override
    public Optional<Item> findById(Long id) {
        Item item = em.find(Item.class, id);
        return Optional.ofNullable(item);
    }

    @Override
    public List<Item> findAll(ItemSearchCond cond) {
        String jpql = "select i from Item i";

        Integer maxPrice = cond.getMaxPrice();
        String itemName = cond.getItemName();

        if (StringUtils.hasText(itemName) || maxPrice != null) {
            jpql += " where";
        }
        boolean andFlag = false;
        if (StringUtils.hasText(itemName)) {
            jpql += " i.itemName like concat('%',:itemName,'%')";
            andFlag = true;
        }
        if (maxPrice != null) {
            if (andFlag) {
                jpql += " and";
            }
            jpql += " i.price <= :maxPrice";
        }
        log.info("jpql={}", jpql);
        TypedQuery<Item> query = em.createQuery(jpql, Item.class);
        if (StringUtils.hasText(itemName)) {
            query.setParameter("itemName", itemName);
        }
        if (maxPrice != null) {
            query.setParameter("maxPrice", maxPrice);
        }
        return query.getResultList();
    }
}

save

  • em.persist(item) : JPA에서 객체를 테이블에 저장할 때는 엔티티 매니저가 제공하는 persist() 메서드를 사용하면 된다.

update

  • JPA는 트랜잭션이 커밋되는 시점에, 변경된 엔티티 객체가 있는지 확인한다. 특정 엔티티 객체가 변경된 경우에는 UPDATE SQL을 실행한다.
  • 트랜잭션 커밋 시점에 JPA가 변경된 엔티티 객체를 찾아서 UPDATE SQL을 수행한다고 이해하면 된다.

findById

  • JPA에서 엔티티 객체를 PK를 기준으로 조회할 때는 find() 를 사용하고 조회 타입과, PK 값을 주면 된다.

findAll

JPQL
  • JPA는 JPQL(Java Persistence Query Language)이라는 객체지향 쿼리 언어를 제공한다.
    주로 여러 데이터를 복잡한 조건으로 조회할 때 사용한다.
    SQL이 테이블을 대상으로 한다면, JPQL은 엔티티 객체를 대상으로 SQL을 실행한다 생각하면 된다.

JPA 적용 - 예외 변환

JPA의 경우 예외가 발생하면 JPA 예외가 발생하게 된다.

  • JPA는 PersistenceException 과 그 하위 예외를 발생시킨다.
    추가로 JPA는 IllegalStateException , IllegalArgumentException 을 발생시킬 수 있다.

예외 변환 전

예외 변환 후

@Repository의 기능

  • @Repository 가 붙은 클래스는 컴포넌트 스캔의 대상이 된다.
  • @Repository 가 붙은 클래스는 예외 변환 AOP의 적용 대상이 된다.
  • 스프링과 JPA를 함께 사용하는 경우 스프링은 JPA 예외 변환기 ( PersistenceExceptionTranslator )를 등록한다.
  • 예외 변환 AOP 프록시는 JPA 관련 예외가 발생하면
    JPA 예외 변환기를 통해 발생한 예외를 스프링 데이터 접근 예외로 변환한다.
profile
저장소

0개의 댓글