이번 프로젝트에서 Spring boot + JPA + Gradle 을 적용하면서 헷갈렸던 부분, 알게 된 부분에 대해서 적기 위해 작성했습니다.
김영한님의 JPA 강의를 듣고 적용하는 과정에서 Maven말고 Gradle로 프로젝트를 진행했는데, 다른 점이 있다보니 조금 헤맸습니다.
먼저 Gradle에서 META/persistence.xml을 작성해도 정상적으로 작동하는지 확인해보기로 했습니다.
start.spring.io에서 프로젝트를 다음과 같이 생성한다음
(Gradle로 생성, Spring Data JPA 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는 Java Persistence API의 약자로, 스프링에서 제공하는 것이 아닌 자바 어플리케이션에서 관계형 디비를 사용하는 방식에 대해 정의한 인터페이스이다.
즉, JPA는 특정 기능을 수행하는 라이브러리 같은 개념이 아니라 서버 동작 방식이나, API가 동작하는 방식을 설명하는 것처럼 개념을 정의한 것이었습니다.
JPA는 JAVA에서 제공하는 단순한 명세이기 때문에 이에 대한 구현은 없습니다.
JPA 자체는 인터페이스이기 때문에 우리는 이를 구현해서 실제로 동작하게 해야합니다. 이를 제공하는게 바로 Hibernate 였습니다.
JPA를 사용하기 위해서는 Hibernate 말고 DataNucleus, EclipseLink와 같은 다른 방법으로 사용 할 수 있습니다.
- 요약: JPA는 기술명세이고, Hibernate는 JPA의 구현체이다.
위의 내용을 정확히 인지하고 현재 직면한 문제를 보니, 무엇을 공부하고 고쳐야 하는지 바로 알 수 있었습니다.
- Spring Data JPA와 Hibernate의 차이
- Gradle에서 Hibernate를 사용하면 xml을 사용?
위의 내용을 토대로 Spring Data JPA, Hibernate 모두 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 공식문서를 참고하면 META-INF/persistence.xml을 정의하고, JPA를 사용 할 수 있다고 나와있습니다.
여기에 정의한 것을 EntityManager로 생성 할 수 있습니다.
즉, Gradle이든 Maven이든 어떤 JPA 구현체를 사용하냐에 따라 구현 방법의 차이가 있었던 것이었습니다. 실제로 Gradle + Hibernate를 사용하면 persistence.xml을 사용해도 상관 없었습니다.
-> pom.xml대신 build.gradle에서 groovy를 사용하면서 장점이 있는 것이지 xml을 아예 사용하지 않는 것은 아니었습니다 ㅎㅎ;
정리하자면
@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 표준 명세서이지 기술이 아니다.
+ 추가 할 내용이나 부족한 부분이 있다면, 댓글 작성 부탁드립니다! :)
[출처]
김영한님의 스프링부트 기초편 + JPA책을 이용해서 공부하고 하던 중에 이 부분에서 막혀서 어려웠는데, 잘 포스팅해주셔서 감사합니다!