Spring Data JPA 이용
데이터베이스 액세스에 대한 프레임워크로 Spring Framework에 포함되어 있는 것이 “Spring Data JPA “이다. 이것은 문장 그대로 JPA를 이용하여 데이터 액세스를 위한 것이다. 그 기본적인 사용법에 대해 설명한다.
Spring Data JPA와 pom.xml
데이터베이스 관련은 다양한 라이브러리와 프레임워크가 가장 많이 포함되어 있는 분야이다. Hibernate 등 ORM(Object Relational Mapping)은 SQL 등을 사용하는 데이터베이스의 액세스와 Java의 Objective 코드와 일관성을 위한 기술로 널리 사용되고 있다.
그러한 ORM 관련 기술 중에서도 Java의 순정 기술으로 스며들어 있는 것이 “JPA(Java Persistence API)“이다. 아무튼, JPA 자체는 ORM을 위한 기술이라기 보다는 SQL을 Java 나름대로 쉽게 사용할 것이라는 느낌이지만, 데이터베이스 및 Java 오브젝트의 중개 역할을 위한 기본적인 기술로 많은 프레임워크에서도 사용되고 있다.
Spring Framework에도 JPA를 이용하여 데이터베이스에 액세스를 하는 ‘Spring Data JPA’라는 라이브러리가 포함되어 있다. 이것은 “Spring Data"라는 데이터베이스 액세스 관련 라이브러리 중 하나이다. 이 밖에 비(非)SQL인 MongoDB를 이용하는 “Spring Data MongoDB"와 Hadoop 이용을 위한 “Spring Data Hadoop"등의 것이 준비되어 있다. Spring Data JPA는 일반적인 SQL 의한 관계형 데이터베이스 전반을 이용하기 위한 것으로, Spring Data의 기본이 되는 라이브러리라고 해도 좋을 것이다.
그럼, 이 Spring Data JPA를 이용하여 보기로 하자. 우선 pom.xml에 라이브러리 추가한다. 아래와 같이 소스 코드를 재 작성한다. 예제로, Spring Framework 4.1.7에 맞는 버전으로 구성되어 있다.
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>MySpringApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<!-- Database (H2) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.187</version>
</dependency>
<!-- JPA Provider (Hibernate) -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.8.1.RELEASE</version>
</dependency>
</dependencies>
</project>
이번에는 총 3가지의 <dependency>
태그를 새롭게 추가하였다. 각각 간단히 설명을 하겠다.
H2
그룹 ID에 “com.h2database” 아티팩트(Artifact) ID에 “h2"를 지정하고 있다. H2는 Java SQL 데이터베이스 엔진이다. 데이터베이스 파일에 직접 액세스하여 데이터를 저장할 수 있다. 보통 데이터베이스라고 하면 MySQL이나 PostgreSQL 등이 떠오를 것이다. Java 라이브러리로 구현된 H2와 같은 데이터베이스 엔진은 데이터베이스 서버의 설치 등이 번거로운 일을 할 필요가 없고, 부담없이 이용할 수 있으므로, 학습용으로 적합하다. 그래서 이번에는 H2를 데이터베이스에 이용하여 Spring Data JPA를 사용한다.
Hibernate EntityManager
JPA에는 “엔티티"라는 형태로 데이터베이스의 데이터를 오브젝트화한다. 이 엔티티를 관리하는 것이 엔티티 관리자(EntityManager)이다. 이것은 여러 가지가 있지만, 스스로 사용하기 쉬운 것을 선택해서 구성 이용 가능하도록 되어 있다. 이번에는 Hibernate가 생성하는 엔티티 관리자를 사용하고 있다. 그룹 ID “org.hibernate” Artifact ID은 “hibernate-entitymanager"로 지정한다.
Spring Data JPA
이것이 Spring Data JPA의 본체 라이브러리이다. 그룹 ID는 “org.springframework.data”, 아티팩트 ID가 “spring-data-jpa"을 각각 지정한다.
이상 3개의 라이브러리를 pom.xml에 추가하여 Spring Data JPA를 사용할 수 있게 된다. H2는 다른 데이터베이스 서버를 사용하는 경우는 물론 필요하지 않는다.
persistence.xml 생성
우선 Bean 설정 파일을 이용하는 형태로 Spring Data JPA를 사용해보기로 하자.
Spring Data JPA를 사용하려면 프로젝트에 몇 가지 준비해야 하는 것이 있다. 그 중 하나가 “persistence.xml"라는 파일이다. 이 파일은 “지속성 단위(Persistence unit)“이라고하는 정보를 포함하고 있다.
JPA에서 데이터베이스 액세스를 실행하기 위하여 “지속성"이라는 것을 제공한다. 즉, 이 persistence.xml 안에는 액세스하는 데이터베이스에 대한 정보를 기술해 두는 것이라고 생각하면 된다.
이 파일은 Web 어플리케이션의 “META-INF” 폴더에 저장한다. Maven 프로젝트인 경우에는 “src"의 “main"에 있는 “resources"폴더가 Web 어플리케이션의 디렉터리이다. 이 “resources"폴더에 “META-INF"라는 폴더를 생성하고, 그 안에 “persistence.xml ‘라는 이름으로 파일을 만들고 아래 목록 아래의 내용을 작성하자.
<?xml version="1.0" encoding="UTF-8"?>
<persistence
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.xsd">
<persistence-unit name="persistence-unit"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.diarect" value="${hibernate.dialect}" />
<property name="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}" />
<property name="javax.persistence.jdbc.driver" value="${db.driver}" />
<property name="javax.persistence.jdbc.url" value="${db.url}" />
<property name="javax.persistence.jdbc.user" value="${db.user}" />
<property name="javax.persistence.jdbc.password" value="${db.password}" />
</properties>
</persistence-unit>
</persistence>
이 persistence.xml에서 <persistence>
태그 내에 <persistence-unit>
태그를 넣는다. 이것이 지속성 단위의 정보를 기술하는 태그이다. 이 안에 <provider>
태그에 “공급자” 클래스를 지정하고, 추가로 <properties>
태그에 필요한 정보를 속성으로 기술하고 있다. 기술되어 있는 속성은 다음과 같다.
hibernate.diarect
hibernate.hbm2ddl.auto
이것들은 HibernatePersistence에 필요하다. Dialect는 데이터베이스와 상호 작용을 하는 클래스이며, 시작 및 종료시 데이터베이스 처리에 대한 설정이다. 여기에서는 H2를 이용하기 위한 Dialect와 시작할 때 새로운 데이터베이스를 준비하고, 종료시 삭제하는 설정을 하고 있다.
javax.persistence.jdbc.driver
javax.persistence.jdbc.url
javax.persistence.jdbc.user
javax.persistence.jdbc.password
이러한 데이터베이스 드라이버, 액세스 URL, 액세스에 사용하는 사용자 이름과 비밀번호 등을 각각 설정해 두는 것이다.
준비되어있는 속성은 사용하는 엔티티 관리자에 의해 다소 달라질 수 있다. 이번에는 Hibernate 라이브러리를 이용하고 있기 때문에, 그것은 전용 값이 속성에 추가되어 있다. 다른 엔티티 관리자를 사용하는 경우에는 또 다른 속성을 사용할 필요가 있을지도 모른다.
application.properties 작성
생성한 persistence.xml의 내용을 살펴보면 <property>
태그에 포함되어있는 속성의 값은 ${XX} 형태로 쓰여 있다. 이것은 속성 파일에 포함되어 있는 값을 집어 넣어서 사용하게 되어있는 것이다.
프로젝트는 “resources"폴더에 “application.properties"라는 속성 파일이 생성하다. 여기에 persitence.xml
에 필요한 값을 기술하는 것이다. 아래와 내용으로 작성 하자.
# Database Configuration
db.driver=org.h2.Driver
db.url=jdbc:h2:mem:datajpa
db.username=sa
db.password=
# Hibernate Configuration
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create-drop
여기에서는 “db. XX"와 같은 항목과 “hibernate. XX"와 같은 항목이 작성되어 있다. db로 시작하는 항목은 데이터베이스 액세스에 대한 기본 설정이다. 데이터베이스 드라이버, 클래스 액세스하는 URL, 사용자 이름, 비밀번호가 있다.
H2에 액세스의 경우, 드라이버는 org.h2.Driver라는 클래스를 지정한다. 또한 액세스 URL은 jdbc:h2:mem:datajpa로 하였다. 이것은 H2 메모리에 “datajpa ‘라는 이름으로 데이터베이스를 준비하는 것을 의미한다. 메모리에 만드는 프로그램 종료 후에는 깨끗이 데이터베이스는 사라진다. 학습용으로는 최적의 사용 방법이다.
만약 메모리가 아닌 하드 디스크에 파일로 저장하고 싶다면 “jdbc:h2:경로"라는 형태로 쓰면 된다. 예를 들어, jdbc:h2:/db/dbdata으로 쓰게 되면 디스크의 “db"폴더에 “dbdata"라는 파일을 만들고 거기에 데이터를 저장한다.
Hibernate 관련은 Diarect 값으로 org.hibernate.dialect.H2Dialect를 지정하고 있다. 이것은 H2용 Dialect 클래스이다. 또 hibernate.hbm2ddl.auto 값에 create-drop 지정있어서, 프로그램 시작시 데이터베이스를 생성하고 종료할 때 삭제하는 것을 의미한다. 이번은 H2의 메모리에 저장하고 있기 때문에, 스펙에 관계없이 종료하면 데이터베이스가 삭제된다.
Bean 설정 파일 생성
다음 준비하는 것은 Bean 설정 파일이다. Spring Data JPA를 사용하는 경우에는 “엔티티 관리자"라는 것을 사용하여 액세스한다. 이것을 생성하기 위해 “엔티티 관리자 팩토리’라는 Bean을 설정 파일에서 추가해야 한다.
그럼 “resources"폴더에 새로운 “dbbean.xml"라는 파일을 만들어 보자. 그리고 아래와 같이 내용을 작성하자.
<?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:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jdbc:embedded-database id="dataSource" type="H2" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
</beans>
이번에는 JPA와 JDBC 태그를 사용하기 위한 속성이 <beans>
태그에 여러가지가 추가되어 있다. 이 태그에는 2개의 Bean 설정 태그가 준비되어 있다.
-
<jdbc:embedded-database>
: 이것은 데이터베이스의 데이터 정보(데이터 소스) 오브젝트에 대한 것이다. id=“dataSource"라고 명시되어 있고, 그 엔티티 관리자 팩토리에서 이 Bean을 사용하기 위한 ID이다. 또한 type=“H2"은 데이터베이스로 H2를 사용하고 있음을 나타낸다. -
<bean id="entityManagerFactory">
: 엔티티 관리자 팩토리의 Bean 정의한다. 클래스에org.springframework.orm.jpa
패키지의LocalContainerEntityManagerFactoryBean
라는 클래스를 지정한다. 속성으로 다음과 같은 항목을 사용할 수 있어야 한다.- dataSource :
<jdbc : embedded-database>
마련한 Bean이 지정된다. - jpaVendorAdapter : JPA 벤더 어댑터라는 것을 지정한다. 여기에서는 HibernateJpaVendorAdapter 클래스의 Bean을 사용할 수 있어야 한다. 또한, 이 Bean에는 generateDdl이라는 속성을 제공하고 데이터베이스를 자동으로 생성할 수 있도록 해야 한다.
- dataSource :
여러가지 Bean이 조합되어 있지만, 결국 모두가 “엔티티 관리자"라는 것을 사용할 수 있도록 하기 위한 것이다라는 점을 잘 이해하도록 하자. 또한 entityManagerFactory
속성은 우리는 Hibernate의 것을 이용하고 있지만, 다른 라이브러리를 사용할 수도 있다. 그런 경우 사용하는 업체 어댑터에 맞추어 주어야 한다.
엔티티 클래스 생성
자, 이제 드디어 Spring Data JPA를 이용하기 위한 사전 준비가 되었다. 여기에서 실제로 Spring Data JPA를 이용하기 위한 코딩에 들어간다.
Spring Data JPA는 데이터베이스에 작성되는 테이블을 다루기 위하여 “엔티티"라는 클래스를 사용한다. 엔티티는 테이블의 구조를 Java 클래스로 재구성 한 것이다. 동시에 테이블에서 검색되는 데이터들도 엔티티의 인스턴스로 처리된다.
아래에 간단한 엔터티 클래스의 샘플로 com.devkuma.spring.db 패키지 “SampleEntity"라는 클래스로 작성하자.
package com.devkuma.spring.db;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class SampleEntity {
@Id
@Column
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
@Column(length=50, nullable=false)
private String name;
@Column(length=100, nullable=true)
private String mail;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public long getId() {
return id;
}
public SampleEntity() {
super();
}
public SampleEntity(String name, String mail) {
this();
this.name = name;
this.mail = mail;
}
public String toString() {
return "SampleEntity [id=" + id + ", name=" + name + ", mail=" + mail + "]";
}
}
엔티티 클래스에서는 테이블에 포함되는 항목을 그대로 필드로 제공한다. 즉, “테이블=클래스”, “컬럼=필드 “라는 느낌으로 정의한다. 주의 할 점은 오직 정의 할뿐만 아니라 각각에 어노테이션을을 붙여 있다는 것이다. 이는 다음에 정리하였다.
@Entity
엔티티 클래스에 붙인다. 이 어노테이션을 붙이는 것으로,이 클래스가 엔터티 클래스임을 나타낸다.@Column
필드에 붙인다. 테이블의 칼럼을 나타내기 위한 것이다. 이것을 붙인 필드는 그 이름과 같은 칼럼의 값을 저장하는 것으로 간주된다. 따라서, 칼럼의 형태와 같은 형태의 값이 아니면 안됩니다. 또한 샘플은이런 식으로 있다. 이것은 ( ) 안에 칼럼 특성을 기술하고 있는 것이다. 이런 방식으로 그 칼럼에 설정해야 속성도 함께 어노테이션을 작성할 수 있다.@Column(length=50, nullable=false)
@Id
이 어노테이션은 최초의 id 필드에만 붙일 수 있다. 기본 키를 나타 내기위한 것이며, 이것을 붙인 필드는 그 테이블의 기본 키 컬럼임을 나타낸다.@GeneratedValue(strategy=GenerationType.AUTO)
이것도 id 필드에 붙여 있다. 이것은 값의 자동 생성에 관한 것이다. strategy=GenerationType.AUTO 값을 지정하면 값을 자동으로 설정하도록 한다.
추가되어 있는 필드는 모두 private으로되어 있으며, Setter/Getter 메소드에 액세스 할 수 있게 되어 있다. 그 외에 두 종류의 생성자와 toString 메소드가 있지만, 이들은 엔티티에 필수는 아니다. 필요에 따라 준비하면 된다.
데이터베이스 이용
그러면 실제로 데이터베이스를 이용하여 보기로 하자. com.devkuma.spring.db 패키지에 “App"클래스를 만들고 아래와 같이 소스 코드를 작성한다.
package com.devkuma.spring.db;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("dbbean.xml");
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
EntityManager manager = factory.createEntityManager();
makeDummyData(manager);
// get list
Query query = manager.createQuery("from SampleEntity");
List list = query.getResultList();
printList(list);
System.out.println("...ok.");
}
// create dummy entity data.
public static void makeDummyData(EntityManager manager) {
EntityTransaction transaction = manager.getTransaction();
transaction.begin();
manager.persist(new SampleEntity("tuyano", "syoda@tuyano.com"));
manager.persist(new SampleEntity("hanako", "hanako@flower"));
manager.persist(new SampleEntity("taro", "taro@yamada"));
manager.persist(new SampleEntity("sachiko", "sachico@happy"));
manager.flush();
transaction.commit();
}
// print all entity.
public static void printList(List list) {
for (Object item : list) {
System.out.println(item);
}
}
}
완성되면 실제로 App 클래스를 실행해 보면, 다음과 같이 텍스트가 출력되는 것을 볼 수 있다.
SampleEntity [id = 1 name = tuyano, mail=syoda@tuyano.com]
SampleEntity [id = 2 name = hanako, mail = hanako @ flower]
SampleEntity [id = 3 name = taro, mail = taro @ yamada]
SampleEntity [id = 4 name = sachiko, mail = sachico @ happy]
... ok.
이것은 더미(dummy)로 마련한 엔티티를 데이터베이스에서 검색하여 표시하고 있는 것이다. 여기에서는 더미 데이터를 생성하기 위한 makeDummyData 메소드와 취득한 목록의 내용을 출력하는 printList 메소드가 준비되어 있다. 그럼 간단히 정리해 보자.
- ApplicationContext 생성
우선은, 언제나 만들었던 ApplicationContext 인스턴스를 준비한다. 여기에서는 dbbean.xml 파일 지정했다.
ApplicationContext app = new ClassPathXmlApplicationContext( "dbbean.xml");
- EntityManagerFactory 인스턴스의 취득
Bean 설정 파일에 준비해 놓은 엔티티 관리자 팩토리 Bean을 얻어 온다. 여기에서는 EntityManagerFactory 클래스의 class 값으로 인수를 지정했다.
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
- EntityManager 작성
준비한 EntityManagerFactory에서 EntityManager를 가져온다. 이것은 createEntityManager라는 메소드를 호출할 뿐이다.
EntityManager manager = factory.createEntityManager();
이것으로 EntityManager가 준비되었다. 다음에는 이를 사용하여 더미 데이터를 저장하거나 혹은 전체 엔티티를 목록으로 얻어 올수 있다.
우선, 이번은 “데이터베이스 이용의 기본"이라고 할 있는 것으로, 중요한 EntityManager를 꺼낼 오는 것까지 알면 된다. 구체적인 데이터베이스 액세스는 다음에 설명 할 예정이다.
Bean 설정 클래스 이용
Bean 설정 파일을 사용하지 않고 클래스로 정의할 수 있다. 이전에 dbbean.xml에서 엔티티 관리자 팩토리를 준비했지만 클래스를 사용하여 같은 것을 해보자.
여기에서는 com.devkuma.spring.db 패키지에 SampleEntityConfig
라는 클래스를 만들고, 거기에 Bean 생성 메소드를 준비하도록 하자. 아래와 같이 샘플로 아래와 같이 소스 코드를 재작성하자.
package com.devkuma.spring.db;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
@Configuration
class SampleEntityConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder =
new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2).build();
}
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter =
new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.devkuma.spring.db");
factory.setDataSource(dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
그리고 App 클래스에 있는 아래 코드를 수정한다.
ApplicationContext app = new ClassPathXmlApplicationContext("dbbean.xml");
아래와 같이 수정한다.
ApplicationContext app = new AnnotationConfigApplicationContext(SampleEntityConfig.class);
이것으로 SampleEntityConfig
클래스를 사용하여 Bean을 작성 할 수 있다. dbbean.xml은 불필요해 졌다. 그뿐만 아니라 persistence.xml도 application.properties도 사실 필요가 없어졌다 (application.properties없이 클래스에 직접 값을 쓰고 있기 때문이다). 클래스를 사용하는 것이 보다 깔끔하게 엔티티 관리자를 준비할 있다는 것을 알 수 있다. 그럼 포인트를 정리해 보자.
DataSource의 작성
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2).build();
DataSource는 EmbeddedDatabaseBuilder라는 클래스의 인스턴스를 만든다. setType에서 데이터베이스 종류을 설정하고, build를 호출하면 생성된다.
EntityManagerFactory 만들기
이것은 조금 귀찮은 작업을 해야 한다. 여기에서 하고 있는 작업을 대충 정리하면 이런 느낌이 될 것이다.
- HibernateJpaVendorAdapter 인스턴스를 생성한다.
- LocalContainerEntityManagerFactoryBean 인스턴스를 생성한다.
- setJpaVendorAdapter에서 LocalContainerEntityManagerFactoryBean에 HibernateJpaVendorAdapter를 설정한다.
- 그밖에 setPackagesToScan, setDataSource 같은 방법으로 속성을 설정한다.
- afterPropertiesSet를 호출한다.
- getObject에서 EntityManager 인스턴스를 가져온다.
이것 저것 해야 할 일이 있어서 귀찮은 느낌이 있긴 있지만, Java 코드만으로 (XML 파일 등) 다른 아무것도 필요 없이 Bean 생성 할 수있는 것을 생각하면, Java 프로그래머으로써는 이쪽 방식이 더 편할 것이다.