Hibernate Annotations を使い始めるときにハマったこと

Hibernateは、オープンソースのORマッピングフレームワークです。
http://www.hibernate.org/

Hibernate Annotationsを使えば、あのくだらん 〜〜.hbm.xml を書かなくてよいとの事で、結構嬉しそうなので使ってみます。
本家のドキュメントと、Kishida's SITE 〜 Java入門講座 の Hibernate Annotationsをちょっぴり参考にしました。


最近は色んなフレームワークがconvention over configurationで楽にできるのでよいですね。struts2+zero configuration+codebehindとか。

そんなわけで、このエントリでは、 Hibernateは 2 の頃にちょろっと触っただけの私が、Hibernate Annotation をセットアップするまでにハマったことを書きます。


hibernate.cfg.xml をどこに置いて良いのかわからなかった

出た例外 : "org.hibernate.HibernateException: Hibernate Dialect must be explicitly set"

  • classpathのルートに置けばよいです。↓とのコンボで一瞬迷いました

AnnotationConfiguration#configure() を呼ぶのを忘れた

出た例外 : "org.hibernate.HibernateException: Hibernate Dialect must be explicitly set"
出た警告 : "WARN UserSuppliedConnectionProvider:23 - No connection properties specified - the user must supply JDBC connections"

  • 本家のドキュメント をコピペしたらおもいっきり抜けてました。
  • AnnotationConfiguration でも、 configureメソッドが必要みたいです。

package-info.javaがないという警告

出た警告 : WARN AnnotationBinder:217 - Package not found or wo package-info.java: パッケージ名

とりあえず、必須ではありません。
対象パッケージにpackage-info.class を置いておくと、この警告が出なくなりました。
初めて知ったんですが、パッケージには package-info.java を置くと javadocにも反映されるそうです。
package-info.java には、ふつう パッケージ名の宣言のみを書いておきます。

間違えて AnnotationConfiguration#addClass を呼んだ

出た例外 : "org.hibernate.MappingNotFoundException: resource: クラス名.hbm.xml not found"

  • アノテートされたクラスの設定をJavaのソースに書くときは、addClassではなく addAnnotatedClass を呼びましょう。

間違えて @org.hibernate.annotations.Entity アノテーション を使った

出た例外 : "org.hibernate.MappingException: Unknown entity: クラス名のQN"
Session#load でこの例外が出ました。
@javax.persistence.Entity を使えとのこと。同様に @org.hibernate.annotations.Table というアノテーションもあるので、間違えそうです。
ソースはHibernate Annotations FAQ

この場合、Criteria#list の結果が空になり、例外も出ないので分かりにくいです。 登録していないエンティティに対しては、例外くらい出してほしいものですが…

getter/setter を使わないとハマる

これは Annotations とは関係ないけれど、マッピング対象のクラスにフィールドを使うと まともに動かない。 
(フィールドに直接アクセスすると lazy initialization が効かないからだと推測する。)

(08/10/30追記) デフォルト(引数なし)コンストラクタがないと例外

(題名の通り) 対象クラスにデフォルトコンストラクタがないと例外が出ます.
引数を持たないコンストラクタを追加すれば例外は発生しません.

org.hibernate.HibernateException: Javassist Enhancement failed: tables.Entry
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxy(JavassistLazyInitializer.java:142)
	at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.getProxy(JavassistProxyFactory.java:72)
	at org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:402)
	at org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3483)
	at org.hibernate.event.def.DefaultLoadEventListener.createProxyIfNecessary(DefaultLoadEventListener.java:298)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:219)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.load(SessionImpl.java:822)
	at org.hibernate.impl.SessionImpl.load(SessionImpl.java:815)
	at test.db.EntryTest1.main(EntryTest1.java:13)
Caused by: java.lang.InstantiationException: tables.Entry_$$_javassist_0
	at java.lang.Class.newInstance0(Class.java:340)
	at java.lang.Class.newInstance(Class.java:308)
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxy(JavassistLazyInitializer.java:139)
	... 10 more
Exception in thread "main" org.hibernate.HibernateException: Javassist Enhancement failed: tables.Entry
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxy(JavassistLazyInitializer.java:142)
	at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.getProxy(JavassistProxyFactory.java:72)
	at org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:402)
	at org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3483)
	at org.hibernate.event.def.DefaultLoadEventListener.createProxyIfNecessary(DefaultLoadEventListener.java:298)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:219)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.load(SessionImpl.java:822)
	at org.hibernate.impl.SessionImpl.load(SessionImpl.java:815)
	at test.db.EntryTest1.main(EntryTest1.java:13)
Caused by: java.lang.InstantiationException: tables.Entry_$$_javassist_0
	at java.lang.Class.newInstance0(Class.java:340)
	at java.lang.Class.newInstance(Class.java:308)
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxy(JavassistLazyInitializer.java:139)
	... 10 more