JPA

  • build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  • application.properties

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE
  • org.hibernate.SQL : ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๊ฐ€ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” SQL์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. logger๋ฅผ ํ†ตํ•ด ์ถœ๋ ฅ ๋œ๋‹ค.

  • org.hibernate.orm.jdbc.bind : SQL์— ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • spring.jpa.show-sql=true : org.hibernate.SQL์™€ ๊ฐ™์ด SQL์ด ์ถœ๋ ฅ๋˜๋Š”๋ฐ System.out์œผ๋กœ ์ถœ๋ ฅ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋กœ๊ทธ๋กœ ๋‚˜์˜ค๋Š” ์œ„ ์„ค์ •์„ ์“ฐ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ๊ฐ์ฒด ๋งคํ•‘

@Data
@Entity
@NoArgsConstructor(access = PROTECTED)
public class Item {

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

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

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}
  • 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) {
        return Optional.ofNullable(em.find(Item.class, id));
    }

    @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();
    }
}
  • Config

@Configuration
public class JpaConfig {

    private final EntityManager em;

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

    @Bean
    public ItemService itemService() {
        return new ItemServiceV1(itemRepository());
    }

    @Bean
    public ItemRepository itemRepository() {
        return new JpaItemRepository(em);
    }
}

@Slf4j
@Import(JpaConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ItemServiceApplication.class, args);
    }
}

EntityManager๋Š” ์ˆœ์ˆ˜ํ•œ JPA๊ธฐ์ˆ ์ด๊ณ  ์Šคํ”„๋ง๊ณผ๋Š” ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค. ๊ทธ๋ž˜์„œ EntityManager๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด JPA ๊ด€๋ จ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

JPA๋Š” PersistenceException๊ณผ ๊ทธ ํ•˜์œ„ ์˜ˆ์™ธ, ์ถ”๊ฐ€๋กœ IllegalArgumentException, IllegalStateException์„ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

JPA ์˜ˆ์™ธ๋ฅผ ์Šคํ”„๋ง ์˜ˆ์™ธ ์ถ”์ƒํ™”(DataAccessException)์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด @Repository๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

img.png

@Repository์˜ ๊ธฐ๋Šฅ

  • ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์˜ ๋Œ€์ƒ์ด ๋œ๋‹ค.

  • ์˜ˆ์™ธ ๋ณ€ํ™˜ AOP์˜ ์ ์šฉ ๋Œ€์ƒ์ด ๋œ๋‹ค.

    • ์Šคํ”„๋ง๊ณผ JPA๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์Šคํ”„๋ง์€ JPA ์˜ˆ์™ธ ๋ณ€ํ™˜๊ธฐ(PersistenceExceptionTranslator)๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.

    • ์˜ˆ์™ธ ๋ณ€ํ™˜ AOP Proxy๋Š” JPA ๊ด€๋ จ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด JPA ์˜ˆ์™ธ ๋ณ€ํ™˜๊ธฐ๋ฅผ ํ†ตํ•ด ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

img_1.png

Last updated