시냅스

Spring JPA 기본 사용법 정리 본문

Java, Spring/JPA

Spring JPA 기본 사용법 정리

ted k 2022. 9. 3. 15:54

JPA, Java Persisitence API

  • 자바의 주력 ORM 데이터 접근 기술이다.
    • ORM(Object-Relational Mapping) 은 객체와 데이터베이스의 관계를 매핑해주는 도구이다.
      • 객체는 객체대로 설계, 데이터베이스는 데이터베이스대로 설계 
      • => 중간에서 ORM이 맵핑한다.
      • 데이터베이스 접근을 프로그래밍 언어의 관점에서 맞출 수 있다.
      • SQL 문을 직접 작성하지 않고 엔티티를 객체로 표현할 수 있다.
      • 객체를 통해 간접적으로 데이터베이스를 다룬다.
  • 대개 Querydsl과 함께 사용한다.
  • 주로 hibernate 구현체를 사용한다.
  • 1차 캐시와 동일성(identity) 를 보장한다
  • 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
  • 지연 로딩(lazy Loading)을 통해 성능 최적화를 할 수 있다.
    • 지연 로딩 : 객체가 실제 사용될 때 로딩
    • 즉시 로딩 : Join sql로 한 번에 연관된 객체가지 미리 조회

 

JPA 구동 방식

용례 (Spring) - ORM 매핑

@Data
@Entity
public class Item {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // db 에서 값 증가
    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가 인식할 수 있는 객체를 선언
  • @Table : 만약 생략한다면 class 이름을 테이블 이름으로 사용한다.
  • @Id 테이블의 PK와 해당 필드를 매핑한다.
  • @GeneratedValue : PK 생성 값을 데이터베이스에서 생성하는 IDENTITY 방식을 사용한다.
  • @Column : 객체의 필드를 테이블의 컬럼과 매핑한다.
    • JPA는 카멜케이스를 언더스코어 케이스로 자동 변환 해주므로 생략이 가능하다

 

용례 (Spring) - insert, update, (단건 다건) 조회

@Repository
@Transactional // jpa는 데이터를 변경할 때 transaction이 필수로 필요하다.
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;
        ArrayList<Object> param = new ArrayList<>();
        if (StringUtils.hasText(itemName)) {
            jpql += " i.itemName like concat('%', :itemName, '%')";
            param.add(itemName);
            andFlag = true;
        }

        if (maxPrice != null) {
            if (andFlag) {
                jpql += " and";
            }
            jpql += " i.price <= :maxPrice";
            param.add(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();
    }
}
  • insert
    • em 을 통해 persist라는 함수를 사용하여 insert 할 수 있다.
  • update 
    • find를 통해 객체를 찾은 뒤 객체의 내용이 변경됐다면 update를 실행한다.
    • JPA 영속성 컨텍스트를 이용한다.
  • 단건 조회
    • find에 class와 PK 값을 넣어준다.
  • 다건 조회
    • jpql을 작성하여 createQuery를 통해 실행하면 query가 나오고, 데이터를 바인딩하면 getResultList로 조회 내용을 받을 수 있다.

 

Spring 을 쓰지 않는 JPA 용례

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaStudyApplication {

	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

		EntityManager em = emf.createEntityManager();
		
		EntityTransaction tx = em.getTransaction();
		
		//트랜잭션 시작
		tx.begin();
		
		try {
			Member member = new Member();
			member.setId(1L);
			member.setName("memberA");
			
			// 저장
			em.persist(member);
            
            		// 조회
            		Member findMember = em.find(Member.class,1L);
			System.out.println("fineMember.id : " + findMember.getId());
			System.out.println("fineMember.name : " + findMember.getName());
            
            		// 조회 후 수정하면 영속성 컨텍스트에 의해 커밋 시점에 DB에 반영된다.
            		findMember.setName("memberB");
			
			//삭제
			em.remove(findMember);

			//commit
			tx.commit();
		}catch (Exception e) {
			tx.rollback();
		}finally {
			em.close();
		}
		emf.close();
	}
}
  • transaction 종료에 대한 여부와 다 쓴 자원은 꼭 close 해야한다.

'Java, Spring > JPA' 카테고리의 다른 글

JPA 상속관계 매핑 정리  (0) 2022.09.17
JPA 연관관계 정리  (0) 2022.09.16
JPA 엔티티 매핑 정리  (0) 2022.09.16
JPA 영속성 컨텍스트 정리  (0) 2022.09.16
Spring Data JPA 정리  (0) 2022.09.03
Comments