ORM比較(2) - Hibernate

JavaのORMと言えば、Hibernateと言われるくらい有名なライブラリです。HibernateJ2EEの標準APIであるJPAに対応しているので、Hibernateをそのまま使う場合とJPA互換の使い方と2通りのデータ取得方法で書いてみます。
公式ページは https://www.hibernate.org/ になってます。

今回使うライブラリは、Hibernate-Core,Hibernate-Annotations,Hibernate-EntityManagerを使うことになります。実際に必要なライブラリは以下の通り。

それでは実際のソースを。
Entityクラスは、クラスにJPAのjavax.persistence.Entityアノテーションを付ければOKです。対応するテーブル名やカラム名などもJPAアノテーションに従います。非常に細かい設定が可能になります。また、前回のActiveObjectsと違い代替Keyは必要なく javax.persistence.Idアノテーションを付けた列がKeyとなります。

ユーザマスタ(テーブル名はHUser)のEntity

@Entity
@Table(name="huser")
public class HUser {
	@Id
	@Column(name="user_id", unique=true)
	public String userId;

	@Column(name="password")
	public String password;

	@ManyToOne()
	@JoinColumn(name="user_group_id")
	public HUserGroup userGroup;
}

ユーザグループ(テーブル名はHUserGroup)のEntity

@Entity
@Table(name="huser_group")
public class HUserGroup {
	@Id
	@Column(name="user_group_id", unique=true)
	public String userGroupId;

	@OneToMany(mappedBy="userGroup")
	public List<HUser> users = new ArrayList<HUser>();
}

コネクションの作成部分はSingletonな実装にしておきます。ここで HibernateのNativeAPIを使うかJPAを使うかで処理が分かれますので、それぞれ別のクラスにしておきます。
まずは、HibernateのNativeAPIを使うクラスです。こちらの設定は、クラスパス内の hibernate.cfg.xmlと言うファイルを探してその内容を使います。

public class HibernateSessionFactory {
	private static final SessionFactory factory_;
	static {
		try {
			factory_ = new AnnotationConfiguration().configure().buildSessionFactory();
		} catch (HibernateException ex) {
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static Session createSession() {
		return factory_.openSession();
	}
}

hibernate.cfg.xmlはこのように記述します。注意点としては、DBの接続設定だけではなく、使用するEntityのクラス名をここに記述する必要があります。

<?xml version="1.0"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
		<property name="hibernate.connection.url">jdbc:postgresql://server:5432/sample_test</property>
		<property name="hibernate.connection.username">postgres</property>
		<property name="hibernate.connection.password">postgres</property>
		<property name="hibernate.connection.pool_size">3</property>
		<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.hbm2ddl.auto">update</property>

		<mapping package="ch.jpn.taoe.orm_comp.hibernate.entity"/>
		<mapping class="ch.jpn.taoe.orm_comp.hibernate.entity.HUserGroup"/>
		<mapping class="ch.jpn.taoe.orm_comp.hibernate.entity.HUser"/>
	</session-factory>
</hibernate-configuration>

JPAAPIを使うクラスは以下のようになります。設定ファイルは、クラスパス内の META-INF/persistence.xml になります。

public class EntityManagerFactory {
	private static final javax.persistence.EntityManagerFactory emf_;
	static {
		try {
			emf_ = Persistence.createEntityManagerFactory("HibernateSample");
		} catch (Exception ex) {
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static EntityManager getEntityManager() {
		return emf_.createEntityManager();
	}
}

persistence.xmlは以下の通り。実際の設定は、hibernate.cfg.xmlに丸投げしてます。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
	xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
	<persistence-unit name="HibernateSample" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>

		<properties>
			<property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />
		</properties>
	</persistence-unit>
</persistence>

最後に、実際にORMを使う部分のソースです。まずHibernateのNativeAPIを使う場合のデータの取得は前述のクラスからSessionを取得後に、Session#createCriteria の戻り値に Criteria#list を呼び出すことで全件取得ができます。JPAの場合には、前述のクラスからEntityManagerを取得し、EntityManager#createQueryの引数に JPQLを渡すことでデータの取得ができます。
データのInsertを行う部分は長くなるので省略してあります。最後にソースが公開してありますので、そちらを参照してください。

public class Main {
	public static void createNativeTestData() { /*省略*/ }
	public static void createJpaTestData() { /*省略*/ }

	public static void main(String[] args) {
		if (false) createNativeTestData();
		if (false) createJpaTestData();

		System.out.println("Select HibernateNative Query:");
		{
			Session session = HibernateSessionFactory.createSession();
			List<HUserGroup> list = session.createCriteria(HUserGroup.class).list();
			for (HUserGroup group: list) {
				System.out.println(group.userGroupId + ":");
				for (HUser user: group.users) {
					System.out.println("  " + user.userId + "/" + user.password);
				}
			}
			session.close();
		}
		System.out.println("Select HibernateJPA Query:");
		{
			EntityManager em = EntityManagerFactory.getEntityManager();
			List<HUserGroup> list = em.createQuery("select g from HUserGroup g").getResultList();
			for (HUserGroup group: list) {
				System.out.println(group.userGroupId + ":");
				for (HUser user: group.users) {
					System.out.println("  " + user.userId + "/" + user.password);
				}
			}
			em.close();
		}
	}
}

以上です。

上記のソースは、Subversionにて http://taoe.jpn.ch:8080/svn/trunk/orm_compare/Hibernate から取得できます。良かったら自分で動かしてみてください*1

*1:やっぱりPostgreSQLが必要になります