Java

[JPA, Hibernate] 시작하기 -2, JPA 및 Spring Data JPA 사용하기

ride-dev 2023. 12. 23. 19:04

1. JPA 사용하기

1. JPA @Entity class 만들기

@Entity(name = "Course_Details") // Java Bean과 테이블 이름을 다르게 설정할 수 있습니다.
public class Course {
    @Id //table의 기본키를 설정하고
    private long id;
    @Column(name = "name") // column과 매핑합니다(동일하다면 굳이 사용하지 않아도 됩니다)
    private String name;
    private String author;
//
}

앞서 사용한 JDBC의 경우, Java코드는 간단했지만, 쿼리는 복잡해질 수 있는 구조였습니다.

테이블을 많이 사용하면 할수록 Repository클래스의 크기는 방대해질 겁니다.

JPA를 활용하면 Course Bean을 DB에 존재하는 테이블로 직접 매핑하게 됩니다.

DB에 있는 테이블과 POJO를 매핑합니다.

JPA는 @Entity를 활용하여

Java Bean과 테이블 사이에 매핑을 생성하고

그 매핑을 이용해서 값을 삽입하고

값을 검색하고 테이블에서 작업을 수행합니다.

2. JPA @Repository 만들기

@Repository
@Transactional //JPA 쿼리 실행마다 트랜잭션 허용
public class CourseJpaRepository {

    @PersistenceContext // @Autowiring 보다 더 구체적인 어노테이션
    private EntityManager entityManager;

    public void insert(Course course) {
        entityManager.merge(course); // column 삽입 메서드
    }

    public Course findById(long id) {
        return entityManager.find(Course.class, id);
    }

    public void deleteById(long id) {
        Course course = entityManager.find(Course.class, id);
        entityManager.remove(course);
    }
}

JPA @Repository 클래스입니다.

JDBC 보다 간단해진 것을 확인할 수 있습니다.

3. 결과 확인하기

@Component
public class CourseCommandLineRunner implements CommandLineRunner {

    @Autowired
    private CourseJdbcRepository jdbcRepository;

    @Autowired
    private CourseJpaRepository jpaRepository;

    @Override
    public void run(String... args) throws Exception {
        jdbcRepository.insert(new Course(1, "Learn Spring", "ride"));
        jdbcRepository.insert(new Course(2, "Learn Spring JDBC", "ride"));
        jdbcRepository.insert(new Course(3, "Learn Spring JPA", "ride"));
        jdbcRepository.deleteById(1);
        System.out.println(jdbcRepository.findById(2));
        System.out.println(jdbcRepository.findById(3));

        jpaRepository.insert(new Course(4, "Learn Spring JPA2", "ride"));
        jpaRepository.insert(new Course(5, "Learn Spring JPA3", "ride"));
        jpaRepository.deleteById(4);
        System.out.println(jpaRepository.findById(5));
    }
}

위 코드에서 JPA를 사용한 명령어의 출력값은 아래와 같습니다.

Course{id=2, name='Learn Spring JDBC', author='ride'}
Course{id=3, name='Learn Spring JPA', author='ride'}
Course{id=5, name='Learn Spring JPA3', author='ride'}

application.properties 에서 프로퍼티를 추가하면

spring.jpa.show-sql=true

콘솔 창에서 JPA를 통해 실행되는 쿼리를 확인할 수 있습니다.

//
Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: insert into course (author,name,id) values (?,?,?)

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: insert into course (author,name,id) values (?,?,?)

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: delete from course where id=?

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Course{id=5, name='Learn Spring JPA3', author='ride'}

 

JPA를 사용하면,

쿼리를 신경 쓰지 않고 데이터를 쉽게 삽입할 수 있습니다.

알맞은 EntityManager 메서드를 호출하는 것에만 집중하면 됩니다.

2. Spring Data JPA 사용하기

JDBC는 SQL쿼리와 Java코드를 많이 작성합니다.

Spring JDBC는 SQL쿼리를 많이 작성하지만 Java코드는 적게 작성합니다.

JPA는 SQL쿼리를 신경 쓰지 않고 Entity를 Table에 매핑하여 EntityManager로 활용하기만 하면 됩니다.

Spring DataJPA는 간편해진 JPA입니다. EntityManager도 신경 쓸 필요가 없습니다.

1. Spring Data JPA @Repository 만들기

@Repository
public interface CourseSpringDataJpaRepository extends JpaRepository<Course, Long> {
    //JpaRepository<엔터티, 엔터티 기본키>
}

2. 결과 확인하기

@Component
public class CourseCommandLineRunner implements CommandLineRunner {

    @Autowired
    private CourseJdbcRepository jdbcRepository;

    @Autowired
    private CourseJpaRepository jpaRepository;

    @Autowired
    private CourseSpringDataJpaRepository springDataJpaRepository;

    @Override
    public void run(String... args) throws Exception {
        jdbcRepository.insert(new Course(1, "Learn Spring", "ride"));
        jdbcRepository.insert(new Course(2, "Learn Spring JDBC", "ride"));
        jdbcRepository.insert(new Course(3, "Learn Spring JPA", "ride"));
        jdbcRepository.deleteById(1);
        System.out.println(jdbcRepository.findById(2));
        System.out.println(jdbcRepository.findById(3));

        jpaRepository.insert(new Course(4, "Learn Spring JPA2", "ride"));
        jpaRepository.insert(new Course(5, "Learn Spring JPA3", "ride"));
        jpaRepository.deleteById(4);
        System.out.println(jpaRepository.findById(5));

        System.out.println();

        springDataJpaRepository.save(new Course(6, "Learn Spring Data JPA", "ride"));
        springDataJpaRepository.save(new Course(7, "Learn Spring Data JPA2", "ride"));
        springDataJpaRepository.deleteById(6L);
        System.out.println(springDataJpaRepository.findById(7L));
    }
}

위 코드에서 Spring Data JPA를 사용한 명령어의 출력값은 아래와 같습니다.

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: insert into course (author,name,id) values (?,?,?)

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: insert into course (author,name,id) values (?,?,?)

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Hibernate: delete from course where id=?

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.id=?
Optional[Course{id=7, name='Learn Spring Data JPA2', author='ride'}]

엔터티를 정의하고, 인터페이스를 생성합니다.

그리고 메서드를 사용하면 됩니다.

다양한 메서드가 포함되어 있으며, 명명규칙에 따라 커스텀할 수 있습니다.

@Repository
public interface CourseSpringDataJpaRepository extends JpaRepository<Course, Long> {
    //JpaRepository<엔터티, 엔터티 기본키>

    List<Course> findByAuthor(String author); // author 로 조회
    Course findByAuthorAndName(String author, String name); // author, name 으로 조회
}
System.out.println(springDataJpaRepository.findAll());
System.out.println(springDataJpaRepository.findByAuthor("ride"));
System.out.println(springDataJpaRepository.findByAuthorAndName("ride","Learn Spring Data JPA2"));

위 코드의 출력값은 아래와 같습니다.

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0
[Course{id=2, name='Learn Spring JDBC', author='ride'}, Course{id=3, name='Learn Spring JPA', author='ride'}, Course{id=5, name='Learn Spring JPA3', author='ride'}, Course{id=7, name='Learn Spring Data JPA2', author='ride'}]

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.author=?
[Course{id=2, name='Learn Spring JDBC', author='ride'}, Course{id=3, name='Learn Spring JPA', author='ride'}, Course{id=5, name='Learn Spring JPA3', author='ride'}, Course{id=7, name='Learn Spring Data JPA2', author='ride'}]

Hibernate: select c1_0.id,c1_0.author,c1_0.name from course c1_0 where c1_0.author=? and c1_0.name=?
Course{id=7, name='Learn Spring Data JPA2', author='ride'}

 

Spring Data JPA의 이점을 확인할 수 있었습니다.

728x90