소개
spring-data-jpa는 jpa 기반 저장소를 쉽게 구현하도록 만들어준다. 이중에서도 눈에 띄는 특징들은
- type-safe한 쿼리가 가능하다.
- 공통된 저장소 기능들(CRUD)을 제공해준다.
- @Query 어노테이션을 제공한다.
그 외에도 querydsl의 predicate 제공이나 xml 기반의 entity 매핑등의 특징들도 보인다.
예제
먼저 Spring Project로 프로젝트를 생성하고 dependency를 추가하자.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency>
스프링 프로젝트가 기본 dependency를 등록해주므로 우리는 두개만 더 등록해주자.
다음 Article.java 라는 엔티티를 만들어보자.
Article.java
package com.tistory.jekalmin.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Article {
@Id // primary key
@GeneratedValue // auto increment
private int articleNo;
private int memberNo;
private String title;
private String content;
/* 컬럼명은 필드명이랑 동일하게 된다. 따로 명시해주고 싶으면 @Column을 사용하자 */
/**
* 하이버네이트가 파라미터 없는 생성자를 호출하기 때문에, 파라미터 있는 생성자를 생성했을 경우
* 꼭 파라미터 없는 생성자를 만들어 줘야 한다.
*/
public Article(){}
public Article(int memberNo, String title, String content) {
this.memberNo = memberNo;
this.title = title;
this.content = content;
}
public int getArticleNo() {
return articleNo;
}
@SuppressWarnings("unused")
private void setArticleNo(int articleNo) {
this.articleNo = articleNo;
}
public int getMemberNo() {
return memberNo;
}
public void setMemberNo(int memberNo) {
this.memberNo = memberNo;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article [articleNo=" + articleNo + ", memberNo=" + memberNo
+ ", title=" + title + ", content=" + content + "]";
}
}
그리고 Article 엔티티의 저장소를 만든다.
ArticleRepository.java
package com.tistory.jekalmin.repository;
import org.springframework.data.repository.CrudRepository;
import com.tistory.jekalmin.domain.Article;
public interface ArticleRepository extends CrudRepository<Article, Integer> {
}
이제 applicationContext 설정만 하면 된다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<context:component-scan base-package="com.tistory.jekalmin"/>
<context:annotation-config/>
<jdbc:embedded-database id="dataSource" type="HSQL"></jdbc:embedded-database>
<!-- spring data jpa 설정 -->
<!-- jpa repository가 위치한 패키지 경로 등록 -->
<jpa:repositories base-package="com.tistory.jekalmin.repository" entity-manager-factory-ref="entityManagerFactory"/>
<!-- 하이버네이트의 SessionFactory 에 상응하는 jpa의 EntityManagerFactory 등록 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="dataSource" ref="dataSource"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <!-- Hsql 형식에 맞게 변환해주는 클래스 -->
<prop key="hibernate.connection.pool_size">1</prop>
<prop key="hibernate.connection.shutdown">true</prop> <!-- hsql에 있는 마지막 연결이 끊어지면 데이터베이스 shutdown 하는 플래그 -->
<prop key="hibernate.show_sql">true</prop> <!-- SQL 출력 -->
<prop key="hibernate.hbm2ddl.auto">create</prop> <!-- 테이블 자동 생성 -->
</props>
</property>
<!-- 엔티티 정의된 클래스들이 있는 패키지 등록 -->
<property name="packagesToScan" value="com.tistory.jekalmin.domain"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- spring data jpa 설정 끝 -->
</beans>
설정 부분이 쉽지 않은데, 약간의 주석들이 도움이 되길 바란다.
이제 테스트할 클래스만 만들고 테스트하면 된다.
ArticleRepositoryTest.java
package com.tistory.jekalmin.test;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.tistory.jekalmin.domain.Article;
import com.tistory.jekalmin.repository.ArticleRepository;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/application-config.xml")
public class ArticleRepositoryTest {
@Resource
ArticleRepository articleRepository;
@Test
public void write(){
articleRepository.save(new Article(11, "제목", "내용"));
System.out.println(articleRepository.findAll());
}
}
spring-data-jpa의 가장 강력한 기능중 하나가 Repository의 기본 기능을 제공하는 것 같다. 다만 인터페이스만 선언한 만큼, 나만의 메소드를 추가하는 방법이 조금 까다롭다. 메소드를 추가하는 방법은 다음에 작성하겠다.