Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

12월 10일 : JPA 이슈 디버깅, JpaRepository 본문

🧺 일상다반사/TIL

12월 10일 : JPA 이슈 디버깅, JpaRepository

Chamming2 2023. 12. 10. 13:57

1. 디펜던시 오류 디버깅

TL;DR : JPA가 jakarta.persistence와 javax.persistence 두 버전으로 분화되어 있다.
둘을 혼용하지 않고 jakarta.persistence로 통일해 문제를 해결할 수 있었다.
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

이놈이 없으면 에러는 발생하지 않으나, H2 DB에 접근하지 못하는 문제가 있다.

하지만 위 의존성을 추가하면 H2 Console이 제대로 잡히기는 하나, 

Class org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider does not implement the requested interface jakarta.persistence.spi.PersistenceProvider

라는 익셉션이 발생한다.

무엇이 문제인가 의심했는데, 이를 해결한 과정은 다음과 같다.

2. Jakarta Persistence와 Javax Persistence

내가 작성한 엔티티는 이런 형태였다.

package com.example.entity;

import javax.persistence.Entity; // <---- javax.persistence
import javax.persistence.Id; // <---- javax.persistence

@Entity
public class TodoEntity {
    @Id
    private Long id;
}

그런데 에러로그 중 'does not implement the requested interface jakarta.persistence.spi.PersistenceProvider' 라는 단락의 'jakarta.persistence' 라는 녀석이 'javax.persistence' 와 '유사하나 다른' 도구임을 찾을 수 있었다. (+ 조금 더 자세한 글)

 

그래서 'javax.persistence' 와 'jakarta.persistence' 가 공존하면 안될 것 같아 'javax.persistence' 를 걷어내야 할 것 같았고, 찾아본 결과 내가 hibernate-entitymanager 라는 디펜던시를 pom.xml에 추가한 것을 알 수 있었다.

<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-entitymanager</artifactId>
	<version>5.6.15.Final</version>
</dependency>

(아마 GPT가 알려준 것을 그대로 믿은게 화근인 듯 하다 🥲)

 

hibernate-entitymanager 를 pom.xml에서 제거하고, 엔티티를 정의할 때 사용했던 javax.persistence.Entity 및 Id를 jakarta.persistence로 교체하니 에러 없이 제대로 실행되는 것을 확인할 수 있었다.

It works!

추가로 Hibernate는 내가 pom.xml에 따로 정의할 필요 없이 spring-boot-starter-data-jpa 패키지에 포함되어 제공된다고 하니, hibernate-entitymanager를 직접 추가하지 않도록 하자.

3. @RestController와 @Controller

  • @Controller는 어노테이션을 붙인 클래스가 Spring에서 사용하는 컨트롤러임을 표시한다.
  • @RestController는 @Controller에 @ResponseBody 어노테이션을 추가한 축약형 어노테이션이다.
  • @ResponseBody는 메서드가 리턴하는 값이 서버의 응답 본문에 포함됨을 표시한다.
- 요약
@Controller는 서버가 뷰를 생성하는 전통적인 웹 어플리케이션에 주로 사용된다.
JSON 또는 XML 등으로 RESTful한 웹 서비스를 구현할 때는 @RestController 어노테이션을 주로 사용한다.

 

4. JpaRepository

이제 H2 데이터베이스와 연결은 잘 마쳤으니, CRUD를 해보자.

그런데 CRUD도 내가 직접 정의할 필요 없이, Lombok처럼 자동으로 완성해주는 도구가 있다고 한다.

 

바로 JpaRepository 인데, 이를 위해 엔티티와 레포지토리 클래스를 준비해 보자.

// entity/TodoEntity.java
package com.example.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class TodoEntity {
    @Id
    private Long id;
    private String title;
    private Boolean isCompleted;
}
// repository/TodoRepository.java

package com.example.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.entity.TodoEntity;

// class가 아니라 interface로 정의해야 함에 유의하자!
// class로 정의하면 JpaRepository가 suggest 되지 않는다.
public interface TodoRepository extends JpaRepository<TodoEntity, Long> {

}

JpaRepository를 상속받으면 제네릭의 인자로 전달받은 엔티티 를 다룰 수 있는 메서드들을 만들어준다.

JpaRepository가 생성하는 메서드들

 

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆