例えば street(通り), suburb (都市), state 州), postcode (郵便番号)で構成される Address(住所)クラスを使いましょう。 そうすればコードが再利用しやすくなり、リファクタリングも簡単になります。
識別子プロパティはオプションになっていますが、いくつもの理由から使うべきです。 「人工的」で(被生成の意味。ビジネス上の意味を持たないこと)、 プリミティブ型でない識別子をおすすめします。柔軟性を最大にするためには、 java.lang.Long または java.lang.String を使いましょう。
大きい一枚岩のようなマッピング・ドキュメントはいけません。 例えば com.eg.Foo クラスは、 com/eg/Foo.hbm.xml ファイルにマッピングしましょう。 そうすれば、特にチームで開発を行う場合に、良い結果をもたらします。
マッピング・ファイルは対応するクラス・ファイルと一緒に配置しましょう。
クエリ文字列がANSI標準ではないSQL関数をコールするなら、これは良い習慣です。 クエリ文字列を外に出すと、アプリケーションを他へ移植することが簡単になります。
JDBCのように、変化する値は必ず"?"で置き換えましょう。 具体的な値の代入に文字列操作を使っては、絶対にいけません。 名前つきのパラメータを使うとさらに良いです。
Hibernateでは、アプリケーションがJDBCコネクションを管理することができます。 しかし、これは最後の手段だと思ってください。 もし組み込みのコネクション・プロバイダを使うことができなければ、 net.sf.hibernate.connection.ConnectionProvider の実装を考えてください。
例えば、どこかのライブラリから持ってきたJava型を永続化する必要があるとしましょう。 しかしその型には、コンポーネントとしてマッピングするために必要なアクセサが用意されていないとします。 このような場合は、net.sf.hibernate.UserType を実装することを考えるべきです。 そうすれば、Hibernate型との実装変換を心配せずに、アプリケーションのコードを扱えます。
システムのパフォーマンス・クリティカルな領域では、 (例えば大量の update / delete のような)ある種の操作には、 直接JDBCを利用すると良いかもしれません。 しかし、何がボトルネックなのかが わかる までは待ってください。 そして、直接JDBCを利用するからといって、必ずしも速くなるとは限らないことも理解してください。 直接JDBCを利用する必要があれば、Hibernateの Session をオープンして、 SQLコネクションを使うと良いかもしれません。それならまだ同じトランザクション戦略と、 コネクション・プロバイダを使うことができるからです。
たまに、Sessionが永続状態をデータベースと同期させることがあります。 しかし、もしこれが頻繁に起こるようでは、パフォーマンスに影響が出てきてしまいます。 自動フラッシュを無効にしたり、特定のトランザクションにおけるクエリや操作の順番を変更することで、 不必要なフラッシュを最小限にすることができます。
サーブレット / セッションビーン・アーキテクチャを使うとき、 セッションビーンでロードされた永続オブジェクトを、 サーブレット / JSP層との間でやりとりすることができます。 その際、各リクエストに対して新しいSessionを使ってください。 そしてオブジェクトの永続状態を更新するためには、 Session.update() や Session.saveOrUpdate() を使ってください。
最高のスケーラビリティを得るためには、データベース・トランザクションをできるだけ短くしなければいけません。 しかし、ユーザから見た1つの仕事に対して、長いアプリケーション・トランザクションを実装する 必要があることがしばしばです。アプリケーション・トランザクションは、 クライアントのリクエストとレスポンスのサイクルを、いくつかまたぐものになるかもしれません。 切り離されたオブジェクトを使うか、2層アーキテクチャにおいては、 単にJDBCコネクションからHibernate Sessionを切断し、各後続のリクエストにはそれを再接続してください。 複数のアプリケーション・トランザクション・ユースケースに対して、 1つのSessionを使いまわすことはやめてください。 そうでなければ、古くなったデータを使うことになってしまいます。
これは「最も良い」習慣以上の、必須の習慣です。 例外が発生したときは、Transaction をロールバックして、 Session をクローズしてください。 そうでなければ、Hibernateはメモリの状態が永続状態を正確に表現していることを保証できません。 特別な場合として、与えられた識別子のインスタンスがデータベースに存在するかどうかを判定するために、 Session.load() を使うことはやめてください。 その代わりに find() を使ってください。 しかし、例えば StaleObjectStateException や ObjectNotFoundException のように、復帰可能な例外もいくつか存在します。
eagerな(アウター・ジョイン)フェッチは控えめに使ってください。 JVMレベルでキャッシュされないクラスへのほとんどの関連には、プロキシやlazyコレクションを使ってください。 キャッシュされるクラスへの関連、つまりキャッシュがヒットする可能性が高い関連には、 outer-join="false" として明示的にeagerなフェッチを無効にしてください。 ある特定のユースケースに対してアウター・ジョインによるフェッチが適切なときは、 left join を用いたクエリを使ってください。
インターフェイスを使い、(Hibernateの)データ・アクセスコードを隠蔽してください。 DAO と Thread Local Session パターンを組み合わせてください。 UserType を通してHibernateに関連付けることで、 ハンド・コーディングしたJDBCで永続化するクラスを持つこともできます。 (このアドバイスは「十分大きな」アプリケーションに対してのものです。 つまりテーブルを5個しか使わない(小さな)アプリケーションに対しては当てはまりません。)
セッション・スコープの外でオブジェクトを比較するなら、 equals() と hashCode() を実装しなければいけません。 セッション・スコープの内部では、Javaオブジェクトのアイデンティティは保証されています。 これらのメソッドを実装するなら、決してデータベース識別子を使ってはいけません。 一時的なオブジェクトは識別子の値を持たないため、Hibernateはオブジェクトがセーブされるときに値を代入します。 もしセーブ時にオブジェクトがsetの中にあると、ハッシュ・コードが変更され、 契約が破られてしまいます。 equals() と hashCode() を実装するには、 ユニークなビジネス・キーを使ってください。 つまりクラスのプロパティのユニークな組み合わせを比較するようにしてください。 オブジェクトがsetの内部にある間、このキーは安定でユニークでなければならないことを覚えておいてください (ライフタイム全体でなくても構いません。データベースの主キーと同じように安定ではありません。)。 equals() の比較(lazyローディング)の中では、絶対にコレクションを使わないでください。 そして、プロキシを介する他の関連クラスについても、注意してください。
現実には、many-to-many関連の使いどころはめったにありません。 ほとんどの場合「リンク・テーブル」に付加的な情報が必要になります。 この場合、間のリンク・クラスに2つのone-to-many関連を使う方がずっと良いです。 実際に私たちは、ほとんどの関連がone-to-manyかmany-to-oneだと考えています。 他の関連を使うなら、注意深く、それからそれが本当に必要かどうかを考えてみてください。