以下は「Spring Hibernate の連携の例についてのチュートリアル」です(Spring 4 + Hibernate 3 および Hibernate 4)。
スプリングは最も使用されるJava EEフレームワークのうちの1つであり、ハイバネイトは最も人気のあるORMフレームワークです。そのため、スプリングとハイバネイトの組み合わせはエンタープライズアプリケーションでよく使用されます。最近、私はスプリングチュートリアルとハイバネイトチュートリアルに多くを書いてきましたので、スプリングとハイバネイトの統合についての記事が長い間必要でした。
スプリング ハイバネート
今日のチュートリアルでは、Spring 4を使用してHibernate 3と統合し、同じプロジェクトをHibernate 4を使用するように更新します。SpringとHibernateの両方には多くのバージョンがあり、Spring ORMのアーティファクトはHibernate 3とHibernate 4の両方をサポートしていますので、プロジェクトで使用した依存関係をすべてリストにすることが良いです。ただし、私が注意しているのは、すべてのSpringとHibernateのバージョンが互換性がないことです。下記のバージョンは私の場合動作しましたので、互換性があると考えています。他のバージョンを使用してjava.lang.NoClassDefFoundErrorが発生している場合は、互換性がないことを意味します。これは主にHibernateのクラスがパッケージの移動によってエラーが発生しているためです。たとえば、最新のHibernateではorg.hibernate.engine.FilterDefinitionクラスがorg.hibernate.engine.spi.FilterDefinitionに移動しています。
- Spring Framework Version: 4.0.3.RELEASE
- Hibernate Core and Hibernate EntityManager Version: 3.6.9.Final and 4.3.5.Final
- Spring ORM Version: 4.0.3.RELEASE
データベースのセットアップ
私のプロジェクトではMySQLデータベースを使用しているため、以下のsetup.sqlスクリプトはこの例に必要なテーブルを作成します。
CREATE TABLE `Person` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
commit;
スプリングとハイバネートの統合の例のプロジェクト構造
以下の画像は最終的なプロジェクト構造を示しており、私たちはそれぞれのコンポーネントを一つずつ見ていきます。
Mavenの依存関係
最初に、必要な依存関係とそのバージョンを確認するために、pom.xmlファイルを調べます。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringHibernateExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<!-- <hibernate.version>4.3.5.Final</hibernate.version> -->
<hibernate.version>3.6.9.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring ORM support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
SpringとHibernateの統合プロジェクトには、重要な依存関係があります。
- spring-context and spring-tx for core Spring functionalities. Notice that I am using version 4.0.3.RELEASE.
- spring-orm dependency for Spring ORM support, it’s required for hibernate integration in our spring project.
- hibernate-entitymanager and hibernate-core dependencies for Hibernate framework. Notice that version is 3.6.9.Final, for using Hibernate 4 all we need is to change it to 4.3.5.Final as commented in above pom.xml file.
- mysql-connector-java for MySQL driver for database connection.
モデルクラスまたはエンティティビーン
私たちはHibernateのXMLベースのマッピング、およびJPAアノテーションベースのマッピングの両方を使用することができます。ここでは、HibernateがJPAの実装を提供しているため、マッピングにはJPAアノテーションを使用しています。
package com.scdev.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity bean with JPA annotations
* Hibernate provides JPA implementation
* @author scdev
*
*/
@Entity
@Table(name="Person")
public class Person {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String country;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
DAOクラス
私たちはDAOクラスに2つのメソッドを実装します。1つ目はPersonオブジェクトをテーブルに保存するものであり、2つ目はテーブルからすべてのレコードを取得し、Personのリストを返すものです。
package com.scdev.dao;
import java.util.List;
import com.scdev.model.Person;
public interface PersonDAO {
public void save(Person p);
public List<Person> list();
}
上記のDAOクラスの実装は以下のようになります。
package com.scdev.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.scdev.model.Person;
public class PersonDAOImpl implements PersonDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void save(Person p) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(p);
tx.commit();
session.close();
}
@SuppressWarnings("unchecked")
@Override
public List<Person> list() {
Session session = this.sessionFactory.openSession();
List<Person> personList = session.createQuery("from Person").list();
session.close();
return personList;
}
}
注意してください、ここはHibernate関連のクラスを使用している唯一の場所です。このパターンにより、私たちの実装は柔軟で、他のテクノロジーに移行しやすくなります。例えば、iBatis ORMフレームワークを使用したい場合、iBatisのDAO実装を提供し、Springのビーン設定ファイルを変更するだけで済みます。上記の例では、Hibernateセッションのトランザクション管理を使用していますが、Springの宣言的トランザクション管理(@Transactionalアノテーション)も使用できます。詳しくはSpringのトランザクション管理をご覧ください。
Hibernate 3の統合のためのSpring Bean設定ファイル
まずは、Hibernate 3 の統合に必要なスプリングビーンの設定を見てみましょう。後で詳細に調べます。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
<property name="username" value="scdev" />
<property name="password" value="scdev123" />
</bean>
<!-- Hibernate 3 XML SessionFactory Bean definition-->
<!-- <bean id="hibernate3SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean> -->
<!-- Hibernate 3 Annotation SessionFactory Bean definition-->
<bean id="hibernate3AnnotatedSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.scdev.model.Person</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="personDAO" class="com.scdev.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
</bean>
</beans>
Hibernateにデータベース接続の詳細を提供する方法は2つあります。1つ目は、hibernatePropertiesにすべてを渡し、2つ目はDataSourceを作成し、それをHibernateに渡すことです。私は2番目の方法を好みます。そのため、Apache Commons DBCP依存関係を使用して、データベース接続のプロパティを設定してBasicDataSourceを作成します。SpringとHibernate 3の統合では、2つのクラスが提供されています。1つはXMLベースのHibernateマッピングの場合のorg.springframework.orm.hibernate3.LocalSessionFactoryBean、もう1つはアノテーションベースのマッピングの場合のorg.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBeanです。私はコメントにLocalSessionFactoryBeanのシンプルなBean設定を提供しましたので、XMLベースのマッピングを使用している場合はご覧ください。AnnotationSessionFactoryBeanはLocalSessionFactoryBeanクラスを拡張しており、Hibernateの統合に必要な基本的なプロパティをすべて持っています。このプロパティは自己認識型であり、大部分はHibernateに関連するものですので、詳細には触れません。ただし、hibernatePropertiesやannotatedClassesがどこから来ているのか疑問に思っている場合は、beanクラスのソースコードを見る必要があります。personDAOのbean定義に注目してください。前述したように、他のORMフレームワークに切り替える場合は、ここで実装クラスを変更し、必要な他のプロパティを設定する必要があります。
春の4つのハイバネート3のテストプログラム
私たちのセットアップは準備完了ですので、アプリケーションをテストするために簡単なプログラムを書きましょう。
package com.scdev.main;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.scdev.dao.PersonDAO;
import com.scdev.model.Person;
public class SpringHibernateMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
Person person = new Person();
person.setName("Pankaj"); person.setCountry("India");
personDAO.save(person);
System.out.println("Person::"+person);
List<Person> list = personDAO.list();
for(Person p : list){
System.out.println("Person List::"+p);
}
//close resources
context.close();
}
}
上記のプログラムを実行すると、Hibernateに関連する多くの出力が表示されます。ログの設定が適切に行われていないためですが、これはこのチュートリアルの範囲外です。ただし、次の出力がプログラムによって生成されます。
Person::id=3, name=Pankaj, country=India
Person List::id=1, name=Pankaj, country=India
Person List::id=2, name=Pankaj, country=India
Person List::id=3, name=Pankaj, country=India
スプリング4とハイバネイト4の統合の変更
今度は、Hibernate 3ではなくHibernate 4を使用するために、アプリケーションを変更しましょう。この移行では、以下の設定変更のみが必要です。
-
- pom.xml ファイルで Hibernate のバージョンを 4.3.5.Final に変更します。コメントの上に示されている通りです。
Spring ビーンの設定ファイルを変更してください。ここまでに Spring ビーンの設定ファイルが Spring と Hibernate フレームワークの連携の鍵であることがわかっているはずです。以下の Spring ビーンの設定ファイルは、Spring 4 および Hibernate 4 のバージョンに対応しています。
com.scdev.model.Person
org.hibernate.dialect.MySQLDialectthreadfalse
Hibernate 4 では、SessionFactory ビーンに org.springframework.orm.hibernate4.LocalSessionFactoryBean を使用する必要があります。Spring ORM は Hibernate 3 の両方のクラスを統合し、現在は単一のクラスになりました。これは混乱を避けるために良いです。その他の設定は以前と同じです。
それで、私たちのプロジェクトは成功裏にHibernate 4へ移行しましたね、きれいですよね。単にSpringHibernateMainクラスを変更して、spring4.xmlを使用したビーンの設定にするだけで、以前と同じ出力結果を得ることができます。最終プロジェクトは以下のリンクからダウンロードして、さらに設定を試して学ぶことができます。
Spring Hibernate 統合プロジェクトをダウンロードする。