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=TRACEorg.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๊ฐ ํ์ํ๋ค.

@Repository์ ๊ธฐ๋ฅ
์ปดํฌ๋ํธ ์ค์บ์ ๋์์ด ๋๋ค.
์์ธ ๋ณํ AOP์ ์ ์ฉ ๋์์ด ๋๋ค.
์คํ๋ง๊ณผ JPA๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์คํ๋ง์ JPA ์์ธ ๋ณํ๊ธฐ(
PersistenceExceptionTranslator)๋ฅผ ๋ฑ๋กํ๋ค.์์ธ ๋ณํ AOP Proxy๋ JPA ๊ด๋ จ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด JPA ์์ธ ๋ณํ๊ธฐ๋ฅผ ํตํด ๋ฐ์ํ ์์ธ๋ฅผ ์คํ๋ง ๋ฐ์ดํฐ ์ ๊ทผ ์์ธ๋ก ๋ณํํ๋ค.

Last updated