Saturday, May 17, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 11

HIBERNATE - Relational Persistence for Idiomatic Java
Hibernate Reference Documentation
Hibernateレファレンスドキュメンテーション
3.2.2

Table of Contents(コンテンツテーブル)
Preface(序文)
1. Introduction to Hibernate(Hibernateの紹介)
2. Architecture(アーキテクチャ)
3. Configuration(設定)
4. Persistent Classes(永続クラス)
5. Basic O/R Mapping(基本的なO/Rマッピング)
6. Collection Mapping(コレクションのマッピング)
7. Association Mappings(関連マッピング)
8. Component Mapping(コンポーネントのマッピング)
9. Inheritance Mapping(継承マッピング)
10. Working with objects(オブジェクトを扱う)
11. Transactions And Concurrency(トランザクションと並行性)
11.1. Session and transaction scopes(セッションとトランザクションスコープ)
11.1.1. Unit of work(作業単位)
11.1.2. Long conversations(長い対話)
11.1.3. Considering object identity(オブジェクト識別子を考える)
11.1.4. Common issues(一般的な問題)
11.2. Database transaction demarcation(データトランザクション境界)
11.2.1. Non-managed environment(管理されていない環境)
11.2.2. Using JTA(JTAの使用)
11.2.3. Exception handling(例外ハンドリング)
11.2.4. Transaction timeout(トランザクションのタイムアウト)
11.3. Optimistic concurrency control(楽観的同時実行制御)
11.3.1. Application version checking(アプリケーションによるバージョンチェック)
11.3.2. Extended session and automatic versioning(拡張セッションと自動バージョニング)
11.3.3. Detached objects and automatic versioning(分離されたオブジェクトと自動バージョニング)
11.3.4. Customizing automatic versioning(自動バージョニングのカスタマイズ)
11.4. Pessimistic Locking(悲観的ロック)
11.5. Connection Release Modes(コネクション開放モード)

Chapter 11. Transactions And Concurrency(11章:トランザクションと並行性)
The most important point about Hibernate and concurrency control is that it is very easy to understand. Hibernate directly uses JDBC connections and JTA resources without adding any additional locking behavior. We highly recommend you spend some time with the JDBC, ANSI, and transaction isolation specification of your database management system.
Hibernateと同時実行制御について最も重要な点は、容易に理解できることです。Hibernateは新たなロックの振る舞いを追加しておらず、直接JDBCコネクションとJTAリソースを使用します。JDBCANSI、およびデータベース管理システム(DBMS)のトランザクション分離の仕様を少し時間をかけて勉強することを強く推奨します。
Hibernate does not lock objects in memory. Your application can expect the behavior as defined by the isolation level of your database transactions. Note that thanks to theSession, which is also a transaction-scoped cache, Hibernate provides repeatable reads for lookup by identifier and entity queries (not reporting queries that return scalar values).
Hibernateはメモリ内のオブジェクトをロックしません。アプリケーションは、データベーストランザクションの分離レベルで定義した振る舞いを期待できます。トランザクションスコープのキャッシュでもあるSessionのお陰で、識別子やクエリにより検索したエンティティはリピータブルリードになります(スカラー値を返すようなレポートクエリは違います)。
In addition to versioning for automatic optimistic concurrency control, Hibernate also offers a (minor) API for pessimistic locking of rows, using the SELECT FOR UPDATEsyntax. Optimistic concurrency control and this API are discussed later in this chapter.
バージョニングによる自動的な楽観的同時実行制御に加えて、SELECT FOR UPDATE文を使用して、行を悲観的ロックするための(マイナーな)APIも提供します。楽観的同時実行制御とこのAPIについては、この章の後のほうで議論します。
We start the discussion of concurrency control in Hibernate with the granularity ofConfigurationSessionFactory, and Session, as well as database transactions and long conversations.
データベーストランザクションや長い対話(conversation、ロングトランザクション)だけでなく、ConfigurationSessionFactory、およびSessionという粒度でHibernateが行う同時実行制御の議論を始めます。
11.1. Session and transaction scopes(セッションとトランザクションスコープ)
SessionFactory is an expensive-to-create, threadsafe object intended to be shared by all application threads. It is created once, usually on application startup, from aConfiguration instance.
SessionFactoryは生成することが高価で、スレッドセーフなオブジェクトです。よって、アプリケーションのすべてのスレッドで共有すべきです。通常、アプリケーションの起動時に、Configurationインスタンスから1度だけ生成します。
Session is an inexpensive, non-threadsafe object that should be used once, for a single request, a conversation, single unit of work, and then discarded. A Session will not obtain a JDBC Connection (or a Datasource) unless it is needed, hence consume no resources until used.
Sessionは高価ではなく、スレッドセーフなオブジェクトでもありません。よって、1つの要求や1つの対話、1つの作業単位(unit of work)に対して1度だけ使い、その後で捨てるべきです。Sessionは必要になるまで、JDBCConnection(もしくはDataSource)を獲得しません。ゆえに、実際に使用するときまでリソースを消費しません。
To complete this picture you also have to think about database transactions. A database transaction has to be as short as possible, to reduce lock contention in the database. Long database transactions will prevent your application from scaling to highly concurrent load. Hence, it is almost never good design to hold a database transaction open during user think time, until the unit of work is complete.
この状況を完了させるために、 データベーストランザクションについても考えなければなりません。データベース内のロックの競合を少なくするために、データベーストランザクションは可能な限り短くするべきです。長いデータベーストランザクションは、アプリケーションの高い並列実行性を阻害します。ゆえに、ユーザーが考えている間(作業単位が完了するまで)データベーストランザクションを開いたままにするのは、たいていの場合よい設計とはいえません。
What is the scope of a unit of work? Can a single Hibernate Session span several database transactions or is this a one-to-one relationship of scopes? When should you open and close a Session and how do you demarcate the database transaction boundaries?
作業単位というスコープとは何でしょうか?1つのHibernateSessionは、いくつかのデータベーストランザクションをまたがることができるでしょうか?または、スコープと一対一の関係でしょうか?いつSessionを開き、閉じるべきでしょうか?そして、データベーストランザクション境界をどのように分けるのでしょうか?
11.1.1. Unit of work(作業単位)
First, don't use the session-per-operation antipattern, that is, don't open and close aSession for every simple database call in a single thread! Of course, the same is true for database transactions. Database calls in an application are made using a planned sequence, they are grouped into atomic units of work. (Note that this also means that auto-commit after every single SQL statement is useless in an application, this mode is intended for ad-hoc SQL console work. Hibernate disables, or expects the application server to do so, auto-commit mode immediately.) Database transactions are never optional, all communication with a database has to occur inside a transaction, no matter if you read or write data. As explained, auto-commit behavior for reading data should be avoided, as many small transactions are unlikely to perform better than one clearly defined unit of work. The latter is also much more maintainable and extensible.
1つ目は、session-per-operationアンチパターンを使ってはいけません。すなわち、1つのスレッドの中で、単純なデータベース呼び出しのたびにSessionを開いて、閉じてはいけません!もちろん、データベーストランザクションについても同様です。アプリケーション中のデータベース呼び出しは、計画されたシーケンス(planned sequence)を使い、アトミックな作業単位に分類されます。(1つのSQL文ごとにコミットする自動コミットが、使われないという意味でもあることに注意してください。自動コミットは、SQLコンソールでアドホックな作業をする際に使うものです。Hibernateは直ちに自動コミットモードを無効にします。もしくは、アプリケーションサーバーが無効化することを期待します。)データベーストランザクションはオプションではありません。データベースとのすべての通信は、データの読み込みであっても、書き込みであっても、トランザクションの中で行わなければなりません。説明すると、データ読み込みに対して、自動コミットは避けるべきです。なぜなら、多数の小さなトランザクションは、明確に定義された1つの作業単位と比べて、パフォーマンスがよくなることはありません。後者は保守性や拡張性もよりすぐれています。
The most common pattern in a multi-user client/server application is session-per-request. In this model, a request from the client is send to the server (where the Hibernate persistence layer runs), a new Hibernate Session is opened, and all database operations are executed in this unit of work. Once the work has been completed (and the response for the client has been prepared), the session is flushed and closed. You would also use a single database transaction to serve the clients request, starting and committing it when you open and close the Session. The relationship between the two is one-to-one and this model is a perfect fit for many applications.
マルチユーザーのクライアント/サーバーアプリケーションの中で、最もよく使われるパターンは、session-per-requestです。このモデルの中では、クライアントから(Hibernate永続化層が動作する)サーバーへリクエストが送られ、新しいHibernateSessionが開かれます。そして、この作業単位の中ですべてのデータベース処理が実行されます。作業が完了した(そして、クライアントへのレスポンスが準備できた)時点で、session をフラッシュし、閉じます。クライアントの要求を処理するために、1つのデータベーストランザクションを使用するでしょう。Sessionを開き、閉じる際に、データベーストランザクションを開始し、コミットします。二つの関係は一対一です。このモデルは多くのアプリケーションに完全に適合します。
The challenge lies in the implementation. Hibernate provides built-in management of the "current session" to simplify this pattern. All you have to do is start a transaction when a server request has to be processed, and end the transaction before the response is send to the client. You can do this in any way you like, common solutions areServletFilter, AOP interceptor with a pointcut on the service methods, or a proxy/interception container. An EJB container is a standardized way to implement cross-cutting aspects such as transaction demarcation on EJB session beans, declaratively with CMT. If you decide to use programmatic transaction demarcation, prefer the Hibernate Transaction API shown later in this chapter, for ease of use and code portability.
以降の実装にチャレンジしてください。Hibernateは単純なこのパターンのために、予め組み込まれた「current session」の管理を提供します。サーバーリクエストを処理する際はトランザクションを開始しなければなりません。そして、レスポンスをクライアントに送信する前にトランザクションを終わらせます。好きな方法で実現できます。一般的な解決策はServletFilterやサービスメソッドをポイントカットしてAOPインターセプター、proxy/interception コンテナです。EJBコンテナはEJBセッションビーンをトランザクション境界としてアスペクトをクロスカットする実装の標準的な方法です(CMTによる宣言的)。プログラムによるトランザクション境界を使うと決めた場合、簡単に使うため、互換性のあるコードにするために、この章の後のほうにあるHibernateTransactionAPIのほうがよいです。
Your application code can access a "current session" to process the request by simply calling sessionFactory.getCurrentSession() anywhere and as often as needed. You will always get a Session scoped to the current database transaction. This has to be configured for either resource-local or JTA environments, see Section 2.5, "Contextual Sessions".
アプリケーションのコードは、必要なときにどこでも、何回でも、単にsessionFactory.getCurrentSession()を呼び出すだけで「現在のセッション」にアクセスできます。現在のデータベーストランザクションへのセッションを常に取得します。リソース・ローカルな環境、もしくはJTA環境を構成しなければなりません(Section 2.5, "Contextual Sessions"を参照してください)。
Sometimes it is convenient to extend the scope of a Session and database transaction until the "view has been rendered". This is especially useful in servlet applications that utilize a separate rendering phase after the request has been processed. Extending the database transaction until view rendering is complete is easy to do if you implement your own interceptor. However, it is not easily doable if you rely on EJBs with container-managed transactions, as a transaction will be completed when an EJB method returns, before rendering of any view can start. See the Hibernate website and forum for tips and examples around this Open Session in View pattern.
ときどき、「ビューを描画する」までセッションとデータベーストランザクションのスコープを拡張すると便利なことがあります。これは、要求の処理と描画のフェーズを分けているサーブレットアプリケーションにおいて特に役立ちます。独自のインターセプターを実装すれば、ビューを描画するまでデータベーストランザクションを拡張するのは簡単です。しかし、コンテナ管理トランザクションのEJBに頼る場合は、簡単にはできません。なぜなら、ビューの描画を開始する前に、EJBのメソッドがリターンした際に、トランザクションが完了するためです。このOpen Session in Viewパターンに関連するヒントと例については、HibernateWebサイトやフォーラムを参照してください。
11.1.2. Long conversations(長い対話)
The session-per-request pattern is not the only useful concept you can use to design units of work. Many business processes require a whole series of interactions with the user interleaved with database accesses. In web and enterprise applications it is not acceptable for a database transaction to span a user interaction. Consider the following example:
session-per-requestパターンは、作業単位を設計する際に役立つ考えというだけではありません。多くのビジネスプロセスは、ユーザーとの一連の相互作用全体を要求します。その相互作用には、データベースアクセスが含まれます。Webとエンタープライズアプリケーションでは、データベーストランザクションがユーザとの相互作用にまで渡ることは許されません。次の例をよく考えてみてください。
?         The first screen of a dialog opens, the data seen by the user has been loaded in a particular Session and database transaction. The user is free to modify the objects.
ダイアログの最初の画面が開き、個々のSessionとデータベーストランザクションの中でロードされたデータをユーザーに見せます。ユーザーはオブジェクトを自由に修正できます。
?         The user clicks "Save" after 5 minutes and expects his modifications to be made persistent; he also expects that he was the only person editing this information and that no conflicting modification can occur.
5分後にユーザーは「Save」をクリックし、修正が永続化されるのを期待します。また、この情報を編集したのは自分1人だけで、修正のコンフリクトは発生しないと期待します。
We call this unit of work, from the point of view of the user, a long runningconversation (or application transaction). There are many ways how you can implement this in your application.
この作業単位を(ユーザーの視点で)長期の対話(もしくは、アプリケーショントランザクション)と呼びます。アプリケーションにこれを実装する方法はたくさんあります。
A first naive implementation might keep the Session and database transaction open during user think time, with locks held in the database to prevent concurrent modification, and to guarantee isolation and atomicity. This is of course an anti-pattern, since lock contention would not allow the application to scale with the number of concurrent users.
最初に思いつく実装は、ユーザーが考えている間、Sessionとデータベーストランザクションを開いたままにしておくことです。同時に修正されず、分離と原子性が保証されるように、データベース内のロックは保持したままにします。もちろん、これはアンチパターンです。なぜなら、ロックの競合が発生すると、アプリケーションが同時ユーザー数に応じてスケールアップできなくなるからです。
Clearly, we have to use several database transactions to implement the converastion. In this case, maintaining isolation of business processes becomes the partial responsibility of the application tier. A single conversation usually spans several database transactions. It will be atomic if only one of these database transactions (the last one) stores the updated data, all others simply read data (e.g. in a wizard-style dialog spanning several request/response cycles). This is easier to implement than it might sound, especially if you use Hibernate's features:
明らかに、対話を実装するためには、いくつかのデータベーストランザクションを使用するべきです。この場合、ビジネスプロセスの分離を維持することは、アプリケーション層の責務の1つになります。1つの対話は、通常いくつかのデータベーストランザクションに及びます。データベーストランザクションの1つのみ(最後の1つ)が更新したデータを保存し、他はデータを読むだけであれば、それはアトミックです(例えば、いくつかの要求/応答を繰り返すウィザード形式のダイアログ)。これは聞くより、実装したほうが簡単です。Hibernateの機能を使うのであれば、特に簡単です。
?         Automatic Versioning - Hibernate can do automatic optimistic concurrency control for you, it can automatically detect if a concurrent modification occured during user think time. Usually we only check at the end of the conversation.
自動バージョニング- Hibernateは自動的に楽観的同時実行制御ができます。ユーザーが考えている間に同時に修正がおきた場合、自動的に検出できます。通常、対話の終了時にチェックするだけです。
?         Detached Objects - If you decide to use the already discussed session-per-requestpattern, all loaded instances will be in detached state during user think time. Hibernate allows you to reattach the objects and persist the modifications, the pattern is calledsession-per-request-with-detached-objects. Automatic versioning is used to isolate concurrent modifications.
分離(Detached)オブジェクトすでに議論したsession-per-requestパターンを使うと決定した場合、ロードされたすべてのインスタンスは、ユーザが考えている間は、セッションから分離された状態になります。オブジェクトをセッションに再追加し、修正を永続化できます。これをsession-per-request-with-detached-objectsパターンと呼びます。自動バージョニングを使うことで、同時に行われる修正を分離できます。
?         Extended (or Long) Session - The Hibernate Session may be disconnected from the underlying JDBC connection after the database transaction has been committed, and reconnected when a new client request occurs. This pattern is known as session-per-conversation and makes even reattachment unnecessary. Automatic versioning is used to isolate concurrent modifications and the Session is usually not allowed to be flushed automatically, but explicitely.
拡張(もしくは、長い)セッション- HibernateSessionは、データベーストランザクションをコミットした後、裏で結びついているJDBCコネクションを切断できます。そして、クライアントからの新しい要求が発生した際に、再接続できます。このパターンは、session-per-conversationという名で知られており、オブジェクトをセッションへ再追加することさえ不要にします。自動バージョニングを使うことで、同時に行われる修正を分離できます。通常Sessionを自動的にフラッシュさせず、明示的にフラッシュします。
Both session-per-request-with-detached-objects and session-per-conversation have advantages and disadvantages, we discuss them later in this chapter in the context of optimistic concurrency control.
session-per-request-with-detached-objectssession-per-conversationの2つは、利点と欠点を持っています。これについては、この章の後のほうで、楽観的同時実行制御の文脈の中で議論します。
11.1.3. Considering object identity(オブジェクト識別子を考える)
An application may concurrently access the same persistent state in two differentSessions. However, an instance of a persistent class is never shared between two Sessioninstances. Hence there are two different notions of identity:
アプリケーションは、2つの異なるSessionから同じ永続状態に同時にアクセスできます。しかし、2つのSessionインスタンスが永続性クラスの1つのインスタンスを共有することはできません。ゆえに、識別子には2つの異なる概念があるということになります。
Database Identity(データベース識別子)
foo.getId().equals( bar.getId() )
JVM Identity(JVM識別子)
foo==bar
Then for objects attached to a particular Session (i.e. in the scope of a Session) the two notions are equivalent, and JVM identity for database identity is guaranteed by Hibernate. However, while the application might concurrently access the "same" (persistent identity) business object in two different sessions, the two instances will actually be "different" (JVM identity). Conflicts are resolved using (automatic versioning) at flush/commit time, using an optimistic approach.
個々のSessionに追加されたオブジェクトにとって(すなわち、1つのSessionのスコープの中では)、2つの概念は同じです。データベース同一性とJVM同一性が一致することを、Hibernateが保証します。しかし、アプリケーションが2つの異なるセッションから「同じ」(永続性識別子の)ビジネスオブジェクトに同時にアクセスする限り、2つのインスタンスは実際に(JVM識別子が)「異なり」ます。楽観的アプローチによって、(自動バージョニングの)フラッシュ/コミット時にコンフリクトが解決されます。
This approach leaves Hibernate and the database to worry about concurrency; it also provides the best scalability, since guaranteeing identity in single-threaded units of work only doesn't need expensive locking or other means of synchronization. The application never needs to synchronize on any business object, as long as it sticks to a single thread per Session. Within a Session the application may safely use == to compare objects.
このアプローチでは、Hibernateとデータベースに同時実行についての心配が残ります。一方で、最高のスケーラビリティが提供されます。なぜなら、1スレッドの作業単位の中で一意性が保証されれば、高価なロックや同期化が不要になるためです。Sessionごとに1つのスレッドを貼り付ける限り、アプリケーションはビジネスオブジェクトをsynchronizeする必要はありません。Session内では、アプリケーションはオブジェクトを比較するために、= =を安全に使用できます。
However, an application that uses == outside of a Session, might see unexpected results. This might occur even in some unexpected places, for example, if you put two detached instances into the same Set. Both might have the same database identity (i.e. they represent the same row), but JVM identity is by definition not guaranteed for instances in detached state. The developer has to override the equals() and hashCode() methods in persistent classes and implement his own notion of object equality. There is one caveat: Never use the database identifier to implement equality, use a business key, a combination of unique, usually immutable, attributes. The database identifier will change if a transient object is made persistent. If the transient instance (usually together with detached instances) is held in a Set, changing the hashcode breaks the contract of the Set. Attributes for business keys don't have to be as stable as database primary keys, you only have to guarantee stability as long as the objects are in the sameSet. See the Hibernate website for a more thorough discussion of this issue. Also note that this is not a Hibernate issue, but simply how Java object identity and equality has to be implemented.
けれども、Sessionの外で= =を使うアプリケーションは、予期しない結果に遭遇します。これは予期しない場所で起こりえます。例えば、2つの分離インスタンスを同じSetputしたときなどです。両方とも同じデータベース識別子を持ちます(すなわち、同じ行を表します)。しかし、分離状態のインスタンスのJVM識別子は当然保証されません。開発者は、永続性クラスのequals()hashCode()メソッドをオーバーライドし、オブジェクト等価性の概念を実装すべきです。警告が1つあります。等価性の実装にデータベース識別子を使わないでください。ユニークな(普通は不変の)属性の組み合わせであるビジネスキーを使ってください。もし、一時オブジェクトが永続化された場合、データベース識別子が変わります。一時オブジェクトを(通常分離インスタンスと共に)Setに保持する場合、ハッシュコードが変わるということは、Setの契約を破るということです。ビジネスキーのための属性は、データベースの主キーほど安定すべきではないです。オブジェクトが同じSetの中にいる間だけ、安定を保証すべきです。この問題のより徹底的な議論は、HibernateWebサイトを参照してください。また、これはHibernateの問題ではなく、単にJavaオブジェクトの識別子や等価性をどのように実装すべきかということです。
11.1.4. Common issues(一般的な問題)
Never use the anti-patterns session-per-user-session or session-per-application (of course, there are rare exceptions to this rule). Note that some of the following issues might also appear with the recommended patterns, make sure you understand the implications before making a design decision:
session-per-user-sessionsession-per-applicationアンチパターンは使ってはいけません(もちろん、まれに例外があります)。注意:下記の問題のいくつかは、推奨されるパターンとしても出現します。設計を決定する前に、裏の意味を理解するようにしてください。
?         Session is not thread-safe. Things which are supposed to work concurrently, like HTTP requests, session beans, or Swing workers, will cause race conditions if aSession instance would be shared. If you keep your Hibernate Session in your HttpSession(discussed later), you should consider synchronizing access to your Http session. Otherwise, a user that clicks reload fast enough may use the same Session in two concurrently running threads.
Sessionはスレッドセーフではありません。HTTPリクエスト、セッションBeanSwingワーカーのように、同時実行が可能なものがSessionインスタンスを共有すると、競合状態を引き起こします。(後で議論する)HttpSessionの中でHibernateSessionを保持する場合、HttpSessionへのアクセスを同期化することを考慮すべきです。さもなければ、ユーザーが十分早くリロードをクリックすると、同時に走る2つのスレッドの中で、同じSessionが使われます。
?         An exception thrown by Hibernate means you have to rollback your database transaction and close the Session immediately (discussed later in more detail). If yourSession is bound to the application, you have to stop the application. Rolling back the database transaction doesn't put your business objects back into the state they were at the start of the transaction. This means the database state and the business objects do get out of sync. Usually this is not a problem, because exceptions are not recoverable and you have to start over after rollback anyway.
Hibernateが例外を投げた場合は、データベーストランザクションをロールバックし、直ちにSessionを閉じるべきです(詳細を後で議論します)。Sessionがアプリケーションに結び付けられているのであれば、アプリケーションを停止すべきです。データベーストランザクションをロールバックしても、ビジネスオブジェクトはトランザクションを開始したときの状態に戻りません。これは、データベースの状態とビジネスオブジェクトは同期していないことを意味します。通常これは問題になりません。なぜなら、例外は回復できないからです。とにかくロールバックした後にやり直すべきです。
?         The Session caches every object that is in persistent state (watched and checked for dirty state by Hibernate). This means it grows endlessly until you get an OutOfMemoryException, if you keep it open for a long time or simply load too much data. One solution for this is to call clear() and evict() to manage the Session cache, but you most likely should consider a Stored Procedure if you need mass data operations. Some solutions are shown in Chapter 13, Batch processing. Keeping a Session open for the duration of a user session also means a high probability of stale data.
Sessionは永続(persistent)状態のすべてのオブジェクトをキャッシュします(Hibernateは監視し、ダーティ状態かチェックします)。これは、長い間セッションを開いたままにするか、非常に多くのデータをロードし続けるかした場合は、OutOfMemoryExceptionが発生するまで無限に大きくなることを意味します。解決策の1つは、Sessionキャッシュを管理するために、clear()evict()を呼ぶことです。しかし、大きなデータを処理する必要があるなら、たぶんストアドプロシージャを考慮するべきでしょう。いくつかの解決策は、Chapter 13, Batch processingで紹介されています。ユーザーセッションの間、Sessionを開いたままにするということは、データが新鮮でなくなる確率が高くなることを意味します。
11.2. Database transaction demarcation(データトランザクション境界)
Datatabase (or system) transaction boundaries are always necessary. No communication with the database can occur outside of a database transaction (this seems to confuse many developers who are used to the auto-commit mode). Always use clear transaction boundaries, even for read-only operations. Depending on your isolation level and database capabilities this might not be required but there is no downside if you always demarcate transactions explicitly. Certainly, a single database transaction is going to perform better than many small transactions, even for reading data.
データベース(もしくはシステム)トランザクションの境界は、常に必要です。データベーストランザクションの外で、データベースとの通信は起きません(これは自動コミットモードに慣れている多くの開発者を混乱させるかもしれません)。読み込むだけの操作にでも、いつも明確なトランザクション境界を使用してください。分離レベルとデータベースの能力次第で、これは必要ないかもしれませんが、常にトランザクション境界を明示的に指定しても、マイナス面は全くありません。確かに、1つのデータベーストランザクションは多数の小さなトランザクションより(データの読み込みであっても)パフォーマンスがすぐれています。
A Hibernate application can run in non-managed (i.e. standalone, simple Web- or Swing applications) and managed J2EE environments. In a non-managed environment, Hibernate is usually responsible for its own database connection pool. The application developer has to manually set transaction boundaries, in other words, begin, commit, or rollback database transactions himself. A managed environment usually provides container-managed transactions (CMT), with the transaction assembly defined declaratively in deployment descriptors of EJB session beans, for example. Programmatic transaction demarcation is then no longer necessary.
J2EE環境に管理されていない状態 (すなわち、スタンドアロン、単純なWebSwingアプリケーション)でも、 管理された状態でも、Hibernateアプリケーションを実行できます。 管理されていない環境では、Hiberanteがデータベースのコネクションプールを提供します。 アプリケーション開発者は、トランザクション境界を手動で設定しなければなりません。 言い換えると、データベーストランザクションの開始、コミット、ロールバックを 開発者自身が設定する必要があるということです。通常、管理された環境では、コンテナ管理によるトランザクション(CMT)が提供されます。 例えば、セッションBeanのデプロイメントディスクリプタで宣言的に定義し、 トランザクションを組み立てます。 プログラムによるトランザクション境界はもう必要ありません。
However, it is often desirable to keep your persistence layer portable between non-managed resource-local environments, and systems that can rely on JTA but use BMT instead of CMT. In both cases you'd use programmatic transaction demaracation. Hibernate offers a wrapper API called Transaction that translates into the native transaction system of your deployment environment. This API is actually optional, but we strongly encourage its use unless you are in a CMT session bean.
しかしながら、管理されていないリソース・ローカルな環境とJTAに依存したシステム(CMTではなくBMT)の両方に、永続化層をポータブルに保つのは、しばしば望ましいことです。デプロイ環境のネイティブのトランザクションシステムを呼び出すTransactionというラッパーAPIHibernateが提供します。このAPIを使うかは任意ですが、CMTのセッションBeanを使わないのであれば、使うことを強く推奨します。
Usually, ending a Session involves four distinct phases:
通常、Session終了は、4つの異なるフェーズを含みます。
?         flush the session (セッションのフラッシュ)
?         commit the transaction (トランザクションのコミット)
?         close the session (セッションのクローズ)
?         handle exceptions (例外のハンドリング)
Flushing the session has been discussed earlier, we'll now have a closer look at transaction demarcation and exception handling in both managed- and non-managed environments.
セッションのフラッシュについては、前のほうですでに議論しました。管理された環境と管理されていない環境の両方について、トランザクション境界と例外ハンドリングをもっと詳しく見ていきましょう。
11.2.1. Non-managed environment(管理されていない環境)
If a Hibernate persistence layer runs in a non-managed environment, database connections are usually handled by simple (i.e. non-DataSource) connection pools from which Hibernate obtains connections as needed. The session/transaction handling idiom looks like this:
Hibernate永続化層を管理されていない環境で実装する場合は、通常単純なコネクションプール(すなわちDataSourceではない)によって、データベースコネクションを制御します。Hibernateはそのコネクションプールから必要なコネクションを取得します。セッション/トランザクション制御のイディオムは次のようになります。
// Non-managed environment idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
    tx = sess.beginTransaction();

    // do some work
    ...

    tx.commit();
}
catch (RuntimeException e) {
    if (tx != null) tx.rollback();
    throw e; // or display error message
}
finally {
    sess.close();
}
You don't have to flush() the Session explicitly - the call to commit() automatically triggers the synchronization (depending upon the Section 10.10, "Flushing the Session"for the session. A call to close() marks the end of a session. The main implication ofclose() is that the JDBC connection will be relinquished by the session. This Java code is portable and runs in both non-managed and JTA environments.
明示的にSessionflush()を呼び出すべきではなく、commit()を呼び出すことにより、自動的に同期化処理が実行されます(セッションの Section 10.10, "Flushing the Session"FlushModeに依存している)。close()を呼び出すことにより、セッションの終わりを明確にします。close()が暗黙的に行う主なことは、セッションがJDBCコネクションを開放することです。上記のJavaコードはポータブルであり、管理されていない環境とJTA環境の両方で実行できます。
A much more flexible solution is Hibernate's built-in "current session" context management, as described earlier:
より適応性のある解決策は、Hibernateに予め組み込まれている「current session」コンテキスト管理です。言葉で説明するより下記を見たほうが速いでしょう。
// Non-managed environment idiom with getCurrentSession()
try {
    factory.getCurrentSession().beginTransaction();

    // do some work
    ...

    factory.getCurrentSession().getTransaction().commit();
}
catch (RuntimeException e) {
    factory.getCurrentSession().getTransaction().rollback();
    throw e; // or display error message
}
You will very likely never see these code snippets in a regular application; fatal (system) exceptions should always be caught at the "top". In other words, the code that executes Hibernate calls (in the persistence layer) and the code that handles RuntimeException(and usually can only clean up and exit) are in different layers. The current context management by Hibernate can significantly simplify this design, as all you need is access to a SessionFactory. Exception handling is discussed later in this chapter.
正規のアプリケーションの中では、このようなコードの切れ端を決して見ないでしょう。致命的な(システム)例外は、常に「最上位」でキャッチすべきです。言い換えれば、(永続化層で)Hibernate呼び出しを実行するコードと、RuntimeExceptionを制御する(通常はクリーンアップと終了のみ行うことができる)コードは、別々の層の中にあります。Hibernateによるカレントコンテキスト管理は、この設計をかなり単純にします。必要なのは、SessionFactoryにアクセスすることだけです。例外処理は、この章の後のほうで議論します。
Note that you should select org.hibernate.transaction.JDBCTransactionFactory (which is the default), and for the second example "thread" as yourhibernate.current_session_context_class.
注意:(デフォルトですが)org.hibernate.transaction.JDBCTransactionFactoryを選択するべきです。第2の用例としては、hibernate.current_session_context_class"thread"とするとよいでしょう。
11.2.2. Using JTA(JTAを使用する)
If your persistence layer runs in an application server (e.g. behind EJB session beans), every datasource connection obtained by Hibernate will automatically be part of the global JTA transaction. You can also install a standalone JTA implementation and use it without EJB. Hibernate offers two strategies for JTA integration.
永続化層をアプリケーションサーバー(例えば、EJBセッションBeanの背後)で実行する場合、Hibernateから取得するすべてのデータソースコネクションは、自動的にグローバルJTAトランザクションの一部になります。EJBを使わずに、スタンドアロンのJTA実装を導入することもできます。JTA統合のために、Hibernateは2つの戦略を提供します。
If you use bean-managed transactions (BMT) Hibernate will tell the application server to start and end a BMT transaction if you use the Transaction API. So, the transaction management code is identical to the non-managed environment.
Bean管理トランザクション(BMT)を使い、TransactionAPIを使う場合、HibernateはアプリケーションサーバーにBMTトランザクションの開始と終わりを告げます。すなわち、トランザクション管理のコードは、管理されない環境と同じになります。
// BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
    tx = sess.beginTransaction();

    // do some work
    ...

    tx.commit();
}
catch (RuntimeException e) {
    if (tx != null) tx.rollback();
    throw e; // or display error message
}
finally {
    sess.close();
}
If you want to use a transaction-bound Session, that is, the getCurrentSession()functionality for easy context propagation, you will have to use the JTA UserTransactionAPI directly:
トランザクション境界としてSessionを使いたい場合、簡単にコンテキストを伝播する機能であるgetCurrentSession()があるので、JTAUserTransactionAPIを直接使用すべきでしょう。
// BMT idiom with getCurrentSession()
try {
    UserTransaction tx = (UserTransaction)new InitialContext()
                            .lookup("java:comp/UserTransaction");

    tx.begin();

    // Do some work on Session bound to transaction
    factory.getCurrentSession().load(...);
    factory.getCurrentSession().persist(...);

    tx.commit();
}
catch (RuntimeException e) {
    tx.rollback();
    throw e; // or display error message
}
With CMT, transaction demarcation is done in session bean deployment descriptors, not programatically, hence, the code is reduced to:
CMTでは、トランザクション境界をセッションBeanのデプロイメントディスクリプタで定義し、プログラムでは行いません。ゆえに、コードは次のように少なくなります。
// CMT idiom
 Session sess = factory.getCurrentSession();

 // do some work
 ...
In a CMT/EJB even rollback happens automatically, since an unhandledRuntimeException thrown by a session bean method tells the container to set the global transaction to rollback. This means you do not need to use the Hibernate TransactionAPI at all with BMT or CMT, and you get automatic propagation of the "current" Session bound to the transaction.
CMT/EJBの中では、常にロールバックが自動的に実施されます。なぜなら、セッションビーンのメソッドにより投げられた制御されていないRuntimeExceptionは、グローバルトランザクションをロールバックするようにコンテナに伝えるためです。これは、BMTもしくはCMTといっしょにHibernateTransactionAPIを使う必要は少しもないという意味です。
Note that you should choose org.hibernate.transaction.JTATransactionFactory if you use JTA directly (BMT), and org.hibernate.transaction.CMTTransactionFactory in a CMT session bean, when you configure Hibernate's transaction factory. Remember to also sethibernate.transaction.manager_lookup_class. Furthermore, make sure that yourhibernate.current_session_context_class is either unset (backwards compatiblity), or set to "jta".
Hibernateのトランザクションファクトリを設定する際に、JTAを直接使う(BMTの)場合はorg.hibernate.transaction.JTATransactionFactoryを、CMTセッションビーンの中ではorg.hibernate.transaction.CMTTransactionFactoryを選択すべきだということに注意してください。hibernate.transaction.manager_lookup_classをセットすることも思い出してください。なお、hibernate.current_session_context_classは、セットしないか(後方互換)、"jta"をセットしてください。
The getCurrentSession() operation has one downside in a JTA environment. There is one caveat to the use of after_statement connection release mode, which is then used by default. Due to a silly limitation of the JTA spec, it is not possible for Hibernate to automatically clean up any unclosed ScrollableResults or Iterator instances returned byscroll() or iterate(). You must release the underlying database cursor by callingScrollableResults.close() or Hibernate.close(Iterator) explicity from a finally block. (Of course, most applications can easily avoid using scroll() or iterate() at all from the JTA or CMT code.)
getCurrentSession()オペレーションは、JTA環境では1つの欠点を持ちます。デフォルトで使われるafter_statementコネクションリリースモードを使用する上で、警告が1つあります。JTA仕様の愚かな制約のために、scroll()またはiterate()が返した、閉じられていないScrollableResultsまたはIteratorインスタンスをHibernateが自動的にクリーンアップすることはできません。finallyブロックの中で、ScrollableResults.close()またはHibernate.close(Iterator)を明示的に呼び出して、裏に潜んだデータベースカーソルを解放しなければなりません。(もちろん、多くのアプリケーションでは、JTACMTコードでscroll()iterate()の使用を避けるのは容易です。)
11.2.3. Exception handling(例外ハンドリング)
If the Session throws an exception (including any SQLException), you should immediately rollback the database transaction, call Session.close() and discard the Session instance. Certain methods of Session will not leave the session in a consistent state. No exception thrown by Hibernate can be treated as recoverable. Ensure that the Session will be closed by calling close() in a finally block.
Sessionが例外(SQLExceptionを含む)を投げた場合、直ちに、データベーストランザクションをロールバックし、Session.close()を呼び、Sessionインスタンスを破棄すべきです。Sessionのいくつかのメソッドは、セッションの状態を矛盾したままにします。Hibernateが投げた例外を、回復できるものとして扱うことはできません。finallyブロックの中でclose()を呼んで、Sessionを確実に閉じてください。
The HibernateException, which wraps most of the errors that can occur in a Hibernate persistence layer, is an unchecked exception (it wasn't in older versions of Hibernate). In our opinion, we shouldn't force the application developer to catch an unrecoverable exception at a low layer. In most systems, unchecked and fatal exceptions are handled in one of the first frames of the method call stack (i.e. in higher layers) and an error message is presented to the application user (or some other appropriate action is taken). Note that Hibernate might also throw other unchecked exceptions which are not a HibernateException. These are, again, not recoverable and appropriate action should be taken.
HibernateExceptionは、Hibernate永続化層の中で発生する多くのエラーをラップする、検査されない例外です(Hibernateの古いバージョンは違いました)。私たちの意見は、アプリケーション開発者に回復不可能な例外を下層でキャッチすることを強要すべきではないということです。多くのシステムでは、検査されない例外と致命的な例外は、コールスタックの最初のフレームの1つ(例えば、最上位の層で)でハンドリングし、エラーメッセージをアプリケーションユーザーに表示します(もしくは、他の適切な処理を実施します)。Hibernateは、HibernateException以外の検査されない例外も投げることに注意してください。これらもまた、回復不可能であり、適切な処理を実施すべきです。
Hibernate wraps SQLExceptions thrown while interacting with the database in aJDBCException. In fact, Hibernate will attempt to convert the eexception into a more meningful subclass of JDBCException. The underlying SQLException is always available via JDBCException.getCause(). Hibernate converts the SQLException into an appropriateJDBCException subclass using the SQLExceptionConverter attached to the SessionFactory. By default, the SQLExceptionConverter is defined by the configured dialect; however, it is also possible to plug in a custom implementation (see the javadocs for theSQLExceptionConverterFactory class for details). The standard JDBCException subtypes are:
Hibernateは、データベースとの対話中に投げられたSQLExceptionJDBCExceptionでラップします。実は、例外をより意味のあるJDBCExceptionのサブクラスに変換しようと試みます。元のSQLExceptionは、JDBCException.getCause()によりいつでも得られます。Hibernateは、SessionFactoryに追加されているSQLExceptionConverterを使い、SQLExceptionを適当なJDBCExceptionサブクラスに変換します。デフォルトでは、SQLExceptionConverterは設定されているSQL方言により定義されます。一方で、独自の実装に差し替えることもできます(詳細は、SQLExceptionConverterFactoryクラスのJavadocを参照してください)。標準的なJDBCExceptionのサブタイプを下記に示します。
?         JDBCConnectionException - indicates an error with the underlying JDBC communication.
JDBCConnectionException-基礎となるJDBC通信のエラーを表します。
?         SQLGrammarException - indicates a grammar or syntax problem with the issued SQL.
SQLGrammarException-発行するSQLの文法もしくは構文の問題を表します。
?         ConstraintViolationException - indicates some form of integrity constraint violation.
ConstraintViolationException-何らかの形式の完全性制約違反を表します。
?         LockAcquisitionException - indicates an error acquiring a lock level necessary to perform the requested operation.
LockAcquisitionException-要求された操作を実施するのに必要なロックレベルを得る際のエラーを表します。
?         GenericJDBCException - a generic exception which did not fall into any of the other categories.
GenericJDBCException-他のカテゴリに一致しなかった一般的な例外です。
11.2.4. Transaction timeout(トランザクションのタイムアウト)
One extremely important feature provided by a managed environment like EJB that is never provided for non-managed code is transaction timeout. Transaction timeouts ensure that no misbehaving transaction can indefinitely tie up resources while returning no response to the user. Outside a managed (JTA) environment, Hibernate cannot fully provide this functionality. However, Hibernate can at least control data access operations, ensuring that database level deadlocks and queries with huge result sets are limited by a defined timeout. In a managed environment, Hibernate can delegate transaction timeout to JTA. This functioanlity is abstracted by the Hibernate Transactionobject.
EJBのような管理された環境が提供するきわめて重要な特徴の1つは、トランザクションのタイムアウトです。これは管理されていないコードには提供できません。トランザクションタイムアウトは、不品行なトランザクションがユーザーにレスポンスを返さないまま、無期限にリソースを使い続けないことを保障します。管理された環境(JTA)の外では、Hibernateはこの機能をフルに提供できません。しかしながら、Hibernateは次のようなデータアクセス操作の制御くらいはできます。データベースレベルのデッドロックや大きなリザルトセットを返すクエリを定義されたタイムアウトによって確実に制限します。管理された環境では、HibernateはトランザクションタイムアウトをJTAに委譲します。この機能は、HibernateTransactionオブジェクトによって抽象化されています。

Session sess = factory.openSession();
try {
    //set transaction timeout to 3 seconds
    sess.getTransaction().setTimeout(3);
    sess.getTransaction().begin();

    // do some work
    ...

    sess.getTransaction().commit()
}
catch (RuntimeException e) {
    sess.getTransaction().rollback();
    throw e; // or display error message
}
finally {
    sess.close();
}
Note that setTimeout() may not be called in a CMT bean, where transaction timeouts must be defined declaratively.
CMTビーンの中ではsetTimeout()を呼び出せないことに注意してください。トランザクションタイムアウトは宣言的に定義されるべきです。
11.3. Optimistic concurrency control(楽観的同時実行制御)
The only approach that is consistent with high concurrency and high scalability is optimistic concurrency control with versioning. Version checking uses version numbers, or timestamps, to detect conflicting updates (and to prevent lost updates). Hibernate provides for three possible approaches to writing application code that uses optimistic concurrency. The use cases we show are in the context of long conversations, but version checking also has the benefit of preventing lost updates in single database transactions.
高い並列性と高いスケーラビリティの両方を実現するアプローチは、バージョニングを使った楽観的同時実行制御のみです。更新の衝突を見つけるために(および、更新が失われるのを防ぐために)、バージョン番号もしくはタイムスタンプを使って、バージョンをチェックします。Hibernateは、楽観的同時実行を行うアプリケーションコードを書くためのアプローチを3つ提供します。私たちが見せるユースケースは、長い対話を持ちますが、バージョンチェックはまだ1つのデータベーストランザクションの中で更新を失うことを防ぐ利点も持っています。
11.3.1. Application version checking(アプリケーションによるバージョンチェック)
In an implementation without much help from Hibernate, each interaction with the database occurs in a new Session and the developer is responsible for reloading all persistent instances from the database before manipulating them. This approach forces the application to carry out its own version checking to ensure conversation transaction isolation. This approach is the least efficient in terms of database access. It is the approach most similar to entity EJBs.
Hibernateにほとんど助けてもらわずに実装するケースです。データベースとのやり取りは、それぞれ新しいSessionの中で起こります。開発者は、すべての永続性インスタンスを操作する前に、データベースから再読み込みする責務があります。このアプローチでは、対話トランザクションの分離を守るために、アプリケーション自身がバージョンチェックを行う必要があります。このアプローチは、データベースアクセスの中では、最も非効率です。エンティティEJBと最も似ているアプローチです。
// foo is an instance loaded by a previous Session
session = factory.openSession();
Transaction t = session.beginTransaction();

int oldVersion = foo.getVersion();
session.load( foo, foo.getKey() ); // load the current state
if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();
foo.setProperty("bar");

t.commit();
session.close();
The version property is mapped using <version>, and Hibernate will automatically increment it during flush if the entity is dirty.
<version>を使って、versionプロパティをマッピングします。Hibernateは、エンティティがダーティである場合、フラッシュし、その間にversionプロパティを自動的にインクリメントします。
Of course, if you are operating in a low-data-concurrency environment and don't require version checking, you may use this approach and just skip the version check. In that case, last commit wins will be the default strategy for your long conversations. Keep in mind that this might confuse the users of the application, as they might experience lost updates without error messages or a chance to merge conflicting changes.
もちろん、データの並列性が低い環境で運用しており、バージョンチェックが不要なら、このアプローチを使い、バージョンチェックをスキップするだけです。その場合は、長い対話には、「最後にコミットしたものが勝つ」がデフォルトの戦略でしょう。このアプローチは、アプリケーションのユーザーを混乱させるかもしれないことを心に留めて置いてください。それは、エラーメッセージや競合した変更をマージする機会がないまま、更新を失う経験をするためです。
Clearly, manual version checking is only feasible in very trivial circumstances and not practical for most applications. Often not only single instances, but complete graphs of modified ojects have to be checked. Hibernate offers automatic version checking with either an extended Session or detached instances as the design paradigm.
確かに、マニュアルによるバージョンチェックは、些細な儀式だけで実行できますが、多くのアプリケーションにとって実用的ではありません。しばしば、1つのインスタンスだけでなく、修正されたオブジェクトの完全なグラフをチェックしなければなりません。Hibernateは、設計パラダイムとして、拡張Sessionか分離されたインスタンスを自動的にバージョンチェックします。
11.3.2. Extended session and automatic versioning(拡張セッションと自動バージョニング)
A single Session instance and its persistent instances are used for the whole conversation, known as session-per-conversation. Hibernate checks instance versions at flush time, throwing an exception if concurrent modification is detected. It's up to the developer to catch and handle this exception (common options are the opportunity for the user to merge changes or to restart the business conversation with non-stale data).
1つのSessionインスタンスとその永続性インスタンスは、session-per-conversationとして知られる、対話全体で使われます。Hibernateはフラッシュする際に、インスタンスのバージョンをチェックします。同時に修正されたことを検出すると、例外を投げます。この例外をキャッチして扱うのは、開発者の責任です(一般的な選択肢は、変更をマージするか古くないデータでビジネス対話を再スタートする機会をユーザーに提供することです)。
The Session is disconnected from any underlying JDBC connection when waiting for user interaction. This approach is the most efficient in terms of database access. The application need not concern itself with version checking or with reattaching detached instances, nor does it have to reload instances in every database transaction.
ユーザーの対話を待っているときは、Sessionを基礎となるJDBCコネクションから切り離します。このアプローチは、データベースアクセスの中では、最も効率的です。アプリケーションは、バージョンチェックや分離されたインスタンスを再追加することに関心を持つ必要はありません。また、あらゆるデータベーストランザクションの中でインスタンスを再読み込みする必要はありません。
// foo is an instance loaded earlier by the old session
Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction

foo.setProperty("bar");

session.flush();    // Only for last transaction in conversation
t.commit();         // Also return JDBC connection
session.close();    // Only for last transaction in conversation
The foo object still knows which Session it was loaded in. Beginning a new database transaction on an old session obtains a new connection and resumes the session. Committing a database transaction disconnects a session from the JDBC connection and returns the connection to the pool. After reconnection, to force a version check on data you aren't updating, you may call Session.lock() with LockMode.READ on any objects that might have been updated by another transaction. You don't need to lock any data that you are updating. Usually you would set FlushMode.NEVER on an extended Session, so that only the last database transaction cycle is allowed to actually persist all modifications made in this conversation. Hence, only this last database transaction would include the flush() operation, and then also close() the session to end the conversation.
fooオブジェクトは、自分をロードしたSessionをまだ知っています。古いセッションの上で新しいデータベーストランザクションを開始することで、新しいコネクションを取得し、そのセッションが再開されます。データベーストランザクションをコミットすることで、セッションからJDBCコネクションを切断し、コネクションをプールに返します。再接続した後、更新していないデータのバージョンチェックを強制するために、他のトランザクションにより更新されているかもしれないオブジェクトに関して、LockMode.READをつけてSession.lock()を呼び出すことができます。更新しているデータをロックする必要はありません。通常、拡張SessionFlushMode.NEVERをセットします。最後のデータベーストランザクションの周期でのみ、対話の中で変更されたすべてを実際に永続化させるためです。ゆえに、最後のデータベーストランザクションのみflush()オペレーションを含みます。そして、対話を終わらせるために、セッションもclose()します。
This pattern is problematic if the Session is too big to be stored during user think time, e.g. an HttpSession should be kept as small as possible. As the Session is also the (mandatory) first-level cache and contains all loaded objects, we can probably use this strategy only for a few request/response cycles. You should use a Session only for a single conversation, as it will soon also have stale data.
ユーザーが考慮中に、格納することができないくらいSessionが大きいのであれば、このパターンは問題があります。例えば、HttpSessionは可能な限り小さく保つべきです。Sessionは(強制的に)1次キャッシュでもあり、ロードしたオブジェクトをすべて保持します。おそらく、リクエスト/レスポンスのサイクルが数回であれば、この戦略が使えます。1つの対話のためだけにSessionを使うべきです。なぜなら、すぐに新鮮でないデータを持つためです。
(Note that earlier Hibernate versions required explicit disconnection and reconnection of a Session. These methods are deprecated, as beginning and ending a transaction has the same effect.)
Hibernateの以前のバージョンは、明示的なSessionの切断と再接続が必要だったことに注意してください。これらのメソッドは非推奨になりました。なぜなら、トランザクションの開始と終了は同じ効果があるためです。)
Also note that you should keep the disconnected Session close to the persistence layer. In other words, use an EJB stateful session bean to hold the Session in a three-tier environment, and don't transfer it to the web layer (or even serialize it to a separate tier) to store it in the HttpSession.
切断したSessionを永続化層の近くで保持すべきであることに注意してください。言い換えると、3層環境の中でSessionを保持するために、EJBステートフルセッションBeanを使ってください。HttpSessionに格納するために、Web層に転送しないでください(別の層へのシリアライズもしないでください)。
The extended session pattern, or session-per-conversation, is more difficult to implement with automatic current session context management. You need to supply your own implementation of the CurrentSessionContext for this, see the Hibernate Wiki for examples.
拡張セッションパターン(もしくは、session-per-conversation)は、自動的なカレントセッションコンテキスト管理を実施するより難しい。このために、あなたはCurrentSessionContextの実装を供給する必要があります。Hibernate Wikiにある例を参照してください
11.3.3. Detached objects and automatic versioning(分離されたオブジェクトと自動バージョニング)
Each interaction with the persistent store occurs in a new Session. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another Session and then reattaches them using Session.update()Session.saveOrUpdate(), orSession.merge().
新しいSessionにより、永続化ストア(訳注:DB)との対話が発生します。また一方、同じ永続性インスタンスが、データベースとの対話ごとに再利用されます。アプリケーションは、元々は他のSessionでロードされ、デタッチされたインスタンスの状態を操作します。そして、Session.update()もしくは、Session.saveOrUpdate()Session.merge()を使って、それらのインスタンスを再追加します。
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
Transaction t = session.beginTransaction();
session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded already
t.commit();
session.close();
Again, Hibernate will check instance versions during flush, throwing an exception if conflicting updates occured.
この場合もやはり、Hibernateはフラッシュする際に、インスタンスのバージョンをチェックします。更新の競合が発生した場合には、例外を投げます。
You may also call lock() instead of update() and use LockMode.READ (performing a version check, bypassing all caches) if you are sure that the object has not been modified.
オブジェクトが修正されていないことを確信している場合は、update()の代わりに、LockMode.READを使って、lock()を呼び出すこともできます(すべてのキャッシュを迂回し、バージョンチェックを実施します)。
11.3.4. Customizing automatic versioning(自動バージョニングのカスタマイズ)
You may disable Hibernate's automatic version increment for particular properties and collections by setting the optimistic-lock mapping attribute to false. Hibernate will then no longer increment versions if the property is dirty.
マッピングのoptimistic-lock属性にfalseを設定することにより、特定のプロパティやコレクションのために自動バージョンインクリメントを無効にできます。プロパティがダーティであっても、バージョンをインクリメントしません。
Legacy database schemas are often static and can't be modified. Or, other applications might also access the same database and don't know how to handle version numbers or even timestamps. In both cases, versioning can't rely on a particular column in a table. To force a version check without a version or timestamp property mapping, with a comparison of the state of all fields in a row, turn on optimistic-lock="all" in the <class>mapping. Note that this concepetually only works if Hibernate can compare the old and new state, i.e. if you use a single long Session and not session-per-request-with-detached-objects.
レガシーのデータベーススキーマは、しばしば固定的であり、変更できません。または、他のアプリケーションが同じデータベースにアクセスしなければならず、そのアプリケーションはバージョン番号やタイムスタンプさえ操作する方法を知りません。どちらの場合も、テーブルの特定のカラムを当てにして、バージョニングを行えません。バージョンやタイムスタンプのプロパティをマッピングせずに、バージョンチェックさせるために、<class>マッピングにoptimistic-lock="all"を指定してください。行のすべてのフィールドの状態を比較するようになります。これは、Hibernateが古い状態と新しい状態を比較できる場合に、理論的に動作するだけであることに注意してください。例えば、session-per-request-with-detached-objects ではなく、1つの長いSessionを使う場合です。
Sometimes concurrent modification can be permitted as long as the changes that have been made don't overlap. If you set optimistic-lock="dirty" when mapping the <class>, Hibernate will only compare dirty fields during flush.
ときどき、行われた変更が重ならない限り、同時に行われた変更を受け入れることができます。<class>マッピングにoptimistic-lock="dirty"を設定した場合、フラッシュする際に、Hibernateはダーティフィールドのみを比較します。
In both cases, with dedicated version/timestamp columns or with full/dirty field comparison, Hibernate uses a single UPDATE statement (with an appropriate WHEREclause) per entity to execute the version check and update the information. If you use transitive persistence to cascade reattachment to associated entities, Hibernate might execute uneccessary updates. This is usually not a problem, but on update triggers in the database might be executed even when no changes have been made to detached instances. You can customize this behavior by setting select-before-update="true" in the<class> mapping, forcing Hibernate to SELECT the instance to ensure that changes did actually occur, before updating the row.
専用のバージョン/タイムスタンプのカラムを使う場合、もしくはすべて/ダーティのフィールドを比較する場合どちらであっても、Hibernateはエンティティごとに1つのUPDATE文を(適切なWHERE節と共に)使い、バージョンチェックと情報の更新を行います。関連するエンティティの再追加をカスケードするために、連鎖的な永続化を使用した場合、不必要な更新を実行するかもしれません。これは通常問題になりません。しかし、分離したインスタンスを変更していなくとも、データベースのon updateトリガーが実行されるかもしれません。<class>マッピングにselect-before-update="true"を設定することによって、この振る舞いをカスタマイズできます。確実に変更されたかを確認するために、行を更新する前に、必ずインスタンスをSELECTします。
11.4. Pessimistic Locking(悲観的ロック)
It is not intended that users spend much time worring about locking strategies. Its usually enough to specify an isolation level for the JDBC connections and then simply let the database do all the work. However, advanced users may sometimes wish to obtain exclusive pessimistic locks, or re-obtain locks at the start of a new transaction.
ユーザがロック戦略に悩むのに多くの時間を費やすことを意図していません。通常は、JDBCコネクションに分離レベルを指定し、単にデータベースにすべての仕事をさせれば十分です。しかしながら、高度なユーザは、排他的な悲観的ロックを獲得することか、新しいトランザクションが開始される際にロックを再獲得することをときどき望むかもしれません。
Hibernate will always use the locking mechanism of the database, never lock objects in memory!
Hibernateはいつもデータベースのロックの仕組みを使います。メモリ内のオブジェクトを決してロックしません!
The LockMode class defines the different lock levels that may be acquired by Hibernate. A lock is obtained by the following mechanisms:
LockModeクラスは、Hibernateが獲得できる異なるロックレベルを定義します。以下の仕組みにより、ロックを獲得できます。
?         LockMode.WRITE is acquired automatically when Hibernate updates or inserts a row.
LockMode.WRITEは、Hibernateが行を更新もしくは挿入する際に自動的に得られます。
?         LockMode.UPGRADE may be acquired upon explicit user request using SELECT ... FOR UPDATE on databases which support that syntax.
LockMode.UPGRADEは、データベースでサポートされている文法SELECT ... FOR UPDATEを使った、明示的なユーザー要求により得られるかもしれません。
?         LockMode.UPGRADE_NOWAIT may be acquired upon explicit user request using aSELECT ... FOR UPDATE NOWAIT under Oracle.
LockMode.UPGRADE_NOWAITは、Oracle SELECT ... FOR UPDATE NOWAITを使った、明示的なユーザー要求により得られるかもしれません。
?         LockMode.READ is acquired automatically when Hibernate reads data under Repeatable Read or Serializable isolation level. May be re-acquired by explicit user request.
LockMode.READは、Repeatable ReadもしくはSerializableの分離レベルで、データを読んだ際に自動的に得られます。おそらく、明示的なユーザー要求により、再取得されます。
?         LockMode.NONE represents the absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call toupdate() or saveOrUpdate() also start out in this lock mode.
LockMode.NONEは、ロックしないことを表します。Transactionの終わりに、すべてのオブジェクトはこのロックモードに切り替わります。update()saveOrUpdate()を呼び出すことによって、セッションに関連付けられたオブジェクトも、このロックモードで出発します。
The "explicit user request" is expressed in one of the following ways:
「明示的なユーザー要求」とは、下記の方法の1つで言い表せます。
?         A call to Session.load(), specifying a LockMode.
LockModeを指定したSession.load()の呼び出し。
?         A call to Session.lock().
Session.lock()の呼び出し。
?         A call to Query.setLockMode().
Query.setLockMode()の呼び出し。
If Session.load() is called with UPGRADE or UPGRADE_NOWAIT, and the requested object was not yet loaded by the session, the object is loaded using SELECT ... FOR UPDATE. Ifload() is called for an object that is already loaded with a less restrictive lock than the one requested, Hibernate calls lock() for that object.
UPGRADEもしくはUPGRADE_NOWAITが指定されたSession.load()が呼び出され、かつ要求されたオブジェクトがセッションによってまだロードされていなかった場合は、SELECT ... FOR UPDATEを使って、オブジェクトがロードされます。load()で呼び出されたオブジェクトが、要求されているより制限が少ないロックですでにロードされていた場合は、Hibernateはそのオブジェクトのために、lock()を呼び出します。
Session.lock() performs a version number check if the specified lock mode is READ,UPGRADE or UPGRADE_NOWAIT. (In the case of UPGRADE or UPGRADE_NOWAITSELECT ... FOR UPDATE is used.)
指定されたロックモードがREADもしくは、UPGRADEUPGRADE_NOWAITだった場合、Session.lock()は、バージョン番号のチェックを実施します。(UPGRADEもしくはUPGRADE_NOWAITの場合、SELECT ... FOR UPDATEが使われます。)
If the database does not support the requested lock mode, Hibernate will use an appropriate alternate mode (instead of throwing an exception). This ensures that applications will be portable.
データベースが要求されたロックモードをサポートしていない場合、Hibernateは(例外を投げる代わりに、)適切な代わりのモードを使います。これは、アプリケーションがポータブルであることを保証します。
11.5. Connection Release Modes(コネクション開放モード)
The legacy (2.x) behavior of Hibernate in regards to JDBC connection management was that a Session would obtain a connection when it was first needed and then hold unto that connection until the session was closed. Hibernate 3.x introduced the notion of connection release modes to tell a session how to handle its JDBC connections. Note that the following discussion is pertinent only to connections provided through a configuredConnectionProvider; user-supplied connections are outside the breadth of this discussion. The different release modes are identified by the enumerated values oforg.hibernate.ConnectionReleaseMode:
Hibernateのレガシー(2.x)のJDBCコネクション管理に関する振る舞いは、最初に必要とした際にSessionがコネクションを得るというものでした。そして、セッションが閉じられるまで、そのコネクションを保持しました。Hibernate 3.xは、セッションにJDBCコネクションをどのように制御するかを伝えるコネクション開放モードという概念を導入しました。以降の議論は、構成されたConnectionProviderを通して提供されるコネクションに適切であることに注意してください。異なる開放モードは、org.hibernate.ConnectionReleaseModeに列挙された値により確認されます。
?         ON_CLOSE - is essentially the legacy behavior described above. The Hibernate session obatins a connection when it first needs to perform some JDBC access and holds unto that connection until the session is closed.
ON_CLOSE- 本質的に上記で述べたレガシーの振る舞いです。Hibernateセッションは最初にJDBCアクセスを実行する必要がある際にコネクションを得ます。そして、セッションが閉じられるまで、コネクションを保持します。
?         AFTER_TRANSACTION - says to release connections after aorg.hibernate.Transaction has completed.
AFTER_TRANSACTION- org.hibernate.Transactionが完了した後、コネクションを開放します。
?         AFTER_STATEMENT (also referred to as aggressive release) - says to release connections after each and every statement execution. This aggressive releasing is skipped if that statement leaves open resources associated with the given session; currently the only situation where this occurs is through the use oforg.hibernate.ScrollableResults.
AFTER_STATEMENT(積極的な開放とも呼ばれる) -すべてのステートメントがそれぞれ実行された後、コネクションが開放されます。ステートメントがセッションに関連するリソースを開いたままにする場合は、この積極的な開放はスキップされます。今のところ、これが起こるのはorg.hibernate.ScrollableResultsが使われる場合のみです。
The configuration parameter hibernate.connection.release_mode is used to specify which release mode to use. The possible values:
コンフィグレーションパラメータのhibernate.connection.release_modeは、使用する開放モードを指定するために使います。指定できる値は次の通りです。
?         auto (the default) - this choice delegates to the release mode returned by theorg.hibernate.transaction.TransactionFactory.getDefaultReleaseMode() method. For JTATransactionFactory, this returns ConnectionReleaseMode.AFTER_STATEMENT; for JDBCTransactionFactory, this returns ConnectionReleaseMode.AFTER_TRANSACTION. It is rarely a good idea to change this default behavior as failures due to the value of this setting tend to indicate bugs and/or invalid assumptions in user code.
auto(デフォルト) - これを選択するとorg.hibernate.transaction.TransactionFactory.getDefaultReleaseMode()メソッドによって返される開放モードに委譲されます。このメソッドは、JTATransactionFactoryにはConnectionReleaseMode.AFTER_STATEMENTを返し、JDBCTransactionFactoryにはConnectionReleaseMode.AFTER_TRANSACTIONを返します。このデフォルトの振る舞いを変えてうまくいった試しがありません。それは、この設定値が原因で起こる障害は、ユーザコードの中でバグや間違った条件になりやすいからです。
?         on_close - says to use ConnectionReleaseMode.ON_CLOSE. This setting is left for backwards compatibility, but its use is highly discouraged.
on_close- ConnectionReleaseMode.ON_CLOSEを使います。この設定は後方互換のために残されていますが、使わないことを強く勧めます。
?         after_transaction - says to use ConnectionReleaseMode.AFTER_TRANSACTION. This setting should not be used in JTA environments. Also note that with ConnectionReleaseMode.AFTER_TRANSACTION, if a session is considered to be in auto-commit mode connections will be released as if the release mode were AFTER_STATEMENT.
after_transaction- ConnectionReleaseMode.AFTER_TRANSACTIONを使います。この設定はJTA環境の中では使うべきではありません。ConnectionReleaseMode.AFTER_TRANSACTIONを指定し、自動コミットモードの中では、開放モードがAFTER_STATEMENTであるかのように、コネクションは開放されることに注意してください。
?         after_statement - says to use ConnectionReleaseMode.AFTER_STATEMENT. Additionally, the configured ConnectionProvider is consulted to see if it supports this setting (supportsAggressiveRelease()). If not, the release mode is reset to ConnectionReleaseMode.AFTER_TRANSACTION. This setting is only safe in environments where we can either re-acquire the same underlying JDBC connection each time we make a call into ConnectionProvider.getConnection() or in auto-commit environments where it does not matter whether we get back the same connection.
after_statement- ConnectionReleaseMode.AFTER_STATEMENTを使います。さらに、設定されたConnectionProviderは、この設定 (supportsAggressiveRelease()) をサポートするかどうかを調べるために使用します。もしそうでない場合、開放モードはConnectionReleaseMode.AFTER_TRANSACTIONにリセットされます。この設定は次の環境でのみ安全です。それは、ConnectionProvider.getConnection()を呼び出すたびに基盤となるJDBCコネクションが同じものを取得できるか、同じコネクションが得られることが問題とならない自動コミット環境の中です。

No comments:

Post a Comment