JPA + Gradle 셋팅 및 정리(Hibernate, Spring data Jpa)

hynnch2·2022년 1월 28일
7
post-thumbnail
post-custom-banner

이번 프로젝트에서 Spring boot + JPA + Gradle 을 적용하면서 헷갈렸던 부분, 알게 된 부분에 대해서 적기 위해 작성했습니다.

김영한님의 JPA 강의를 듣고 적용하는 과정에서 Maven말고 Gradle로 프로젝트를 진행했는데, 다른 점이 있다보니 조금 헤맸습니다.


👀 의문점 발생.

  1. JPA 강의에서 persistence.xml을 작성하고 Entity Manager를 생성한다음 JPA 작성을 하는데, Gradle은 xml을 쓰지 않는 것을 장점으로 알고있다.
    (pom.xml대신 build.gradle를 작성한다)
  2. Gradle로 작성할 때 application.properties에 JPA 속성을 작성했기 때문에 persistence.xml을 작성하면 중복 작성이 된다.
  3. Gradle + JPA을 검색해보니 강의에서 사용한 em.persist 구조가 아닌, JpaRepository를 상속한 interface를 작성하여 사용한다.

✏️ 코드 검증 및 작동방식 이해

먼저 Gradle에서 META/persistence.xml을 작성해도 정상적으로 작동하는지 확인해보기로 했습니다.

start.spring.io에서 프로젝트를 다음과 같이 생성한다음

(Gradle로 생성, Spring Data JPA dependency 추가)

  • mysql을 사용하기 위해 추가로 mysql-connector-java dependency를 추가합니다.

강의에서 사용했던 EntityManager를 사용하기 위해 persistence.xml을 다음과 같이 작성했습니다.

(resources/META-INF/persistence.xml)

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="jpabook">
        <properties>
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>

</persistence>

작성을 마치고 main함수를 실행했더니 오류가 발생했습니다.

여기서 내가 알고 있는 뭔가가 잘못됐다는 것을 직감했습니다.
강의에서는 hibernate를 사용했고, 저는 Spring Data JPA를 사용하는데 이 둘이 다르다는 것을 이 때 알았습니다.

그러면 먼저 해결 할 문제가 남았습니다.

JPA와 Hibernate의 차이는 정확히 뭐지?

* JPA

JPA는 Java Persistence API의 약자로, 스프링에서 제공하는 것이 아닌 자바 어플리케이션에서 관계형 디비를 사용하는 방식에 대해 정의한 인터페이스이다.

즉, JPA는 특정 기능을 수행하는 라이브러리 같은 개념이 아니라 서버 동작 방식이나, API가 동작하는 방식을 설명하는 것처럼 개념을 정의한 것이었습니다.

JPA는 JAVA에서 제공하는 단순한 명세이기 때문에 이에 대한 구현은 없습니다.

* Hibernate

JPA 자체는 인터페이스이기 때문에 우리는 이를 구현해서 실제로 동작하게 해야합니다. 이를 제공하는게 바로 Hibernate 였습니다.

JPA를 사용하기 위해서는 Hibernate 말고 DataNucleus, EclipseLink와 같은 다른 방법으로 사용 할 수 있습니다.

  • 요약: JPA는 기술명세이고, Hibernate는 JPA의 구현체이다.

위의 내용을 정확히 인지하고 현재 직면한 문제를 보니, 무엇을 공부하고 고쳐야 하는지 바로 알 수 있었습니다.

  1. Spring Data JPA와 Hibernate의 차이
  2. Gradle에서 Hibernate를 사용하면 xml을 사용?

😲 Spring Data JPA vs Hibernate

위의 내용을 토대로 Spring Data JPA, Hibernate 모두 JPA의 구현체인 것은 짐작 할 수 있었습니다. 그럼 둘의 차이점을 알아야 했습니다.

* Spring Data JPA

Spring Data JPA는 공식 문서를 참고하면 쉽게 정보를 얻을 수 있었습니다.

인터넷에서 찾아봤던 Repository를 생성하고 메소드 이름 규칙을 따르면 쉽게 JPA를 사용할 수 있는 것이 바로 Spring에서 제공한 Spring Data JPA를 사용했기 때문이었습니다.

ex)

interface UserRepository extends JpaRepository<User, Long> {
  long deleteByLastname(String lastname);
  List<User> removeByLastname(String lastname);
}

JpaRepository를 상속해서 JPA를 구현하는 방식이 Spring Data JPA 방식입니다.

JpaRepository의 내부적으로 확인해보면

이런식으로 우리가 Hibernate에서 사용했던 "EntityManager"를 사용하고 있는 것을 확인 할 수 있었습니다.

* Hibernate

Hibernate는 Hibernate 공식문서를 참고하면 META-INF/persistence.xml을 정의하고, JPA를 사용 할 수 있다고 나와있습니다.

여기에 정의한 것을 EntityManager로 생성 할 수 있습니다.

즉, Gradle이든 Maven이든 어떤 JPA 구현체를 사용하냐에 따라 구현 방법의 차이가 있었던 것이었습니다. 실제로 Gradle + Hibernate를 사용하면 persistence.xml을 사용해도 상관 없었습니다.

-> pom.xml대신 build.gradle에서 groovy를 사용하면서 장점이 있는 것이지 xml을 아예 사용하지 않는 것은 아니었습니다 ㅎㅎ;


🙌 해결

정리하자면

  • Spring Data JPA 사용
    application.properties에 정의
    CRUDRepository, JpaRepository를 상속해서 JPA 구현. -> 네이밍 규칙 있음 (네이밍 규칙)
    + EntityManager를 사용하려면 @PersistenceContext 통해 사용가능.
@PersistenceContext
private EntityManager em;

public User insertUser(User user){
	em.persist(user);
    return user;
}
  • Hibernate 사용
    resources/META-INF/persistence.xml에 정의
    EntityManagerFactory에서 EntityManager 생성.
    EntityManager로 각 클래스에 맞춰서 코딩.

  • Gradle에서 xml을 아예 사용하지 않는 것은 아니다.

  • JPA는 JAVA진영 ORM 표준 명세서이지 기술이 아니다.


+ 추가 할 내용이나 부족한 부분이 있다면, 댓글 작성 부탁드립니다! :)


[출처]

profile
more than yesterday
post-custom-banner

2개의 댓글

comment-user-thumbnail
2022년 3월 28일

김영한님의 스프링부트 기초편 + JPA책을 이용해서 공부하고 하던 중에 이 부분에서 막혀서 어려웠는데, 잘 포스팅해주셔서 감사합니다!

답글 달기
comment-user-thumbnail
2023년 3월 14일

저도 김영한님 강의를 지금 역순으로 듣고 있어서, maven 안쓰고 gradle 로 하려니 갑자기 띠용해서 들어왔는데 엄청 꼼꼼하게 잘 정리해주셨네요 감사합니다 !!

답글 달기