JPA -3 기본 CRUD

요한·2025년 6월 8일

JPA

목록 보기
3/4

설정

gradle 의존성

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.mysql:mysql-connector-j'

JPA 사용

JpaRepository VS EntityManager

JpaRepository

JPA에서 제공하는 인터페이스 제공함 

✅ 장점
1. 코드가 매우 간결함 (인터페이스만 선언하면 됨)

2.반복적인 CRUD 코드 제거 - 간결함

3.페이징, 정렬, 쿼리 메서드 등 풍부한 기능 제공 - 빠른동작에는 편리함

⚠️ 단점
1.너무 복잡하거나 동적인 쿼리는 오히려 불편

2.트랜잭션 관리나 영속성 컨트롤이 필요할 땐 제약이 있음 Spring Data JPA가 제공하는 인터페이스 기반 CRUD 도구

3.기본적인 저장, 조회, 삭제 메서드들이 자동으로 구현되어 있음

4.쿼리 메서드만 선언하면 복잡한 SQL 없이도 동작

EntityManager

JPA의 핵심 API, 직접 사용하는 방식

✅ 장점
1.JPQL, Native Query 등을 자유롭게 작성 가능

2.세밀한 트랜잭션 제어 가능

3.복잡한 비즈니스 로직 처리 시 유리

⚠️ 단점
1. 직접 작성해야 하므로 코드량 많음

2.반복 작업이 많아지면 생산성 낮아짐

JpaRepository

사용 방법

DepartmentRe.java

@Repository
public interface DepartmentRe extends JpaRepository<Department, Long> {

}// 인터페이스 선언

설명했듯이 repository를 인터페이스로 하고 JpaRepository 상속받아 사용하고 기본적으로 사용할수 있는 메소드제공됨

package com.pj.portfoliosite.jpa_study.service;

import com.pj.portfoliosite.jpa_study.entity.Department;
import com.pj.portfoliosite.jpa_study.repository.DepartmentRe;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class DepartmentService {

    private final DepartmentRe departmentRe;

    //조회
    public List<Department> findAll() {
        return departmentRe.findAll();
    }
    // 저장
    public void save(Department department) {
         departmentRe.save(department);
    }
    // 삭제
    public void delete(Department department) {
        departmentRe.delete(department);
    }
    // id로 조회
    public Department findById(Long id) {
        return departmentRe.findById(id).orElse(null);
    }
    // 수정
    @Transactional
    public void updateDepartment(Long id, Department department) {
        Department dept = departmentRe.findById(id).orElse(null);
        System.out.println(department.getName().toString());
        dept.setName(department.getName());
    }
}

인터페이스에 구현체가 없어도 제공하는 메서드로 데이터베이스에 데이터를 가져올수있다! 편하긴하네.. ㅎㅎ

EntityManager

@Repository
@Transactional
public class DepartmentRepository{
    @PersistenceContext
    private EntityManager em;
    // 저장하는  메소드
    public void save(Department department) {
        em.persist(department);
    }
    //단일 조회
    public Department findById(Long id) {
        return em.find(Department.class, id);
    }
    
    // 삭제 
    public void delete(Department department) {
        em.remove(department);
    }
    // update 
    public void updateDepartment(Long id,Department department) {
        em.createQuery("UPDATE Department d SET d.name = :name WHERE d.id = :id")
                .setParameter("name", department.getName())
                .setParameter("id", id);
    }
    // 전체 조회
    public List<Department> findByAll() {
        return em.createQuery("select d from Department d", Department.class).getResultList();
    }
}

우리가 JPQL를 사용해서 가져오고 평소에쓰는 SQL문과 별칭쓰는거 같다

오류

1. 트랜잭션 오류

이것은 EntityManger 를 사용할때 트랜잭션 어노테이션이 없으면 나는 오류이다!
JpaRepository 는 트랜잭션 내부에 동작하고 있어서 없어도 되지만 EntityManger를 사용할때는 @Transactional 를 꼭 써주자!

해결

class 상단에 @Transactional 작성

2. id 생성오류


찾아보니 성능때문에 SELECT NEXTVAL() 를 하지않고 id 값을 캐시 저장해서 50개씩 묶어서 하다보니 서버를 재시작할때 +50개씩 되는것이였다.

해결

 	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)

내가 이전에 entity 설계할때 GenerataionType.Auto로 했는데 이거를 IDENTITY 변경후에는 재 실행해도 내가 원하는 데로 저장이된다.
이게 뭔 차이가 있겠지만 성능차이랑 index 최적화 가지고 활용하는 곳이면 잘 생각해서 써야겠다.

글쓴이 생각

흠.. 저는 mybatis를 주로 써서 그런지, JPQL를 활용할수있는 EntityManager가 쓰는게 좋네요!

참고 자료

Git
https://github.com/spring-projects/spring-data-examples/tree/main/jpa
DOCS
https://spring.io/projects/spring-data-jpa
다음 글에는 주인관계에 대해서 CRUD 활용을 작성하겠습니다.
긴글 읽어 주셔서 감사합니다!

profile
코드 깍는 개발자 kangyohan.dev.0421@gmail.com

0개의 댓글