Friday, May 16, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 10

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(オブジェクトを扱う)
10.1. Hibernate object states(オブジェクトを扱う)
10.2. Making objects persistent(オブジェクトを永続状態にする)
10.3. Loading an object(オブジェクトのロード)
10.4. Querying(クエリ)
10.4.1. Executing queries(クエリの実行)
10.4.1.1. Iterating results(結果を反復する)
10.4.1.2. Queries that return tuples(制限されたシーケンスを返すクエリ)
10.4.1.3. Scalar results(スカラー結果)
10.4.1.4. Bind parameters(パラメータのバインド)
10.4.1.5. Pagination(ページ分け)
10.4.1.6. Scrollable iteration(スクロール可能なイテレーション)
10.4.1.7. Externalizing named queries(名前付クエリの外出し)
10.4.2. Filtering collections(コレクションのフィルタリング)
10.4.3. Criteria queries(クライテリアのクエリ)
10.4.4. Queries in native SQL(ネイティブSQLクエリ)
10.5. Modifying persistent objects(永続オブジェクトの修正)
10.6. Modifying detached objects(分離オブジェクトの修正)
10.7. Automatic state detection(自動的な状態検出)
10.8. Deleting persistent objects(永続オブジェクトの削除)
10.9. Replicating object between two different datastores(異なる二つのデータストア間でのオブジェクトのレプリケーション)
10.10. Flushing the Session(セッションのフラッシュ)
10.11. Transitive persistence(連鎖的な永続化)
10.12. Using metadata(メタデータの使用)

Chapter 10. Working with objects(10章:オブジェクトを扱う)
Hibernate is a full object/relational mapping solution that not only shields the developer from the details of the underlying database management system, but also offers state management of objects. This is, contrary to the management of SQLstatements in common JDBC/SQL persistence layers, a very natural object-oriented view of persistence in Java applications.
Hibernate は完全なオブジェクト/リレーショナルマッピングソリューションであり、データベース管理システムの詳細を開発者から隠蔽するだけでなく、 オブジェクトの状態管理も行います。これは、JDBC/SQL永続層と同じようなSQL文の管理とは異なり、Javaアプリケーションにおける永続化に対する、とても自然なオブジェクト指向の考え方を提供します。
In other words, Hibernate application developers should always think about the state of their objects, and not necessarily about the execution of SQL statements. This part is taken care of by Hibernate and is only relevant for the application developer when tuning the performance of the system.
言いかえれば、Hibernateを用いるアプリケーション開発者は、オブジェクトの状態については常に意識すべきであり、SQL文の実行については必ずしもそうではありません。この部分は、通常、Hibernateが処理し、システムのパフォーマンスをチューニングするときにだけ、 問題になってきます。
10.1. Hibernate object states(Hibernateにおけるオブジェクトの状態)
Hibernate defines and supports the following object states:
Hibernateは次のようなオブジェクトの状態を定義し、サポートしています。
?         Transient - an object is transient if it has just been instantiated using the newoperator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application doesn't hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).
一時的(Transient) -new演算子を使って インスタンス化されただけで、 HibernateSessionに関連付けられていないオブジェクトは、 一時的(transient)です。それは、データベースに永続的な表現を持たず、識別子となる値は割り当てられていません。一時的なインスタンスは、アプリケーションがその参照をどこにも保持しない場合に、 ガベージコレクタによって破棄されます。オブジェクトを永続的(persistent)な状態にするためには、HibernateSessionを使いましょう。(この状態遷移に必要となるSQL文の発行は、Hibernateに任せましょう。)
?         Persistent - a persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session. Hibernate will detect any changes made to an object in persistent state and synchronize the state with the database when the unit of work completes. Developers don't execute manual UPDATE statements, or DELETE statements when an object should be made transient.
永続的(Persistent)-永続的なインスタンスはデータベースに 永続的な表現を持ち、識別子となる値を持っています。それは、セーブされたり、ロードされたりするかもしれませんが、定義上は、Sessionのスコープの中に存在しています。Hibernateは、作業単位(Unit of work)が完了したときに、 永続状態のオブジェクトに加えられた変更を検出し、オブジェクトの状態とデータベースを同期します。 オブジェクトを一時的(transient)にするときは、開発者は、手作業でUPDATE文やDELETE文を実行しません。
?         Detached - a detached instance is an object that has been persistent, but itsSession has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again. This feature enables a programming model for long running units of work that require user think-time. We call them application transactions, i.e. a unit of work from the point of view of the user.
分離(Detached)- 分離されたインスタンスとは、永続化されているが、それと関連付いていたSessionがクローズされているオブジェクトのことです。そのオブジェクトへの参照は、依然として有効です。そして、もちろん、分離された状態にあるオブジェクトは、修正することさえできます。分離されたインスタンスは、もう一度永続化したい(そして、すべての変更を永続化したい)ときに、 新しいSessionに再追加できます。この機能は、ユーザが考える時間を必要とするような、長期間に及ぶ作業単位に対する プログラミングモデルを可能にします。我々は、これをアプリケーションのトランザクション(applicationtransactions)と呼んでいます。 すなわち、ユーザから見た作業単位だということです。
We'll now discuss the states and state transitions (and the Hibernate methods that trigger a transition) in more detail.
これから、状態と状態遷移(そして遷移のきっかけとなるHibernateのメソッド)について詳細に述べます。
10.2. Making objects persistent(オブジェクトを永続状態にする)
Newly instantiated instances of a a persistent class are considered transient by Hibernate. We can make a transient instance persistent by associating it with a session:
新しくインスタンス化された永続クラスのインスタンスは、 Hibernateでは一時的(transient)と見なされます。以下のように、セッションと関連づけることで、一時的なインスタンスを永続状態(persistent)にできます。
DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
Long generatedId = (Long) sess.save(fritz);
If Cat has a generated identifier, the identifier is generated and assigned to the catwhen save() is called. If Cat has an assigned identifier, or a composite key, the identifier should be assigned to the cat instance before calling save(). You may also usepersist() instead of save(), with the semantics defined in the EJB3 early draft.
Catクラスの識別子が自動生成されるのであれば、save()が呼ばれるときに、 識別子が生成され、catインスタンスに割り当てられます。Catの識別子が他から割り当てられる(assigned識別子を持つ)か、複合キーであるなら、save()を呼び出す前に、識別子を割り当てなければなりません。save()の代わりに、EJB3 の初期ドラフトで定義されたpersist()を使うことも可能です。
Alternatively, you may assign the identifier using an overloaded version of save().
変わりに、識別子を引数にとる、save()メソッドを使って、識別子を割り当てることも出来ます。
DomesticCat pk = new DomesticCat();
pk.setColor(Color.TABBY);
pk.setSex('F');
pk.setName("PK");
pk.setKittens( new HashSet() );
pk.addKitten(fritz);
sess.save( pk, new Long(1234) );
If the object you make persistent has associated objects (e.g. the kittens collection in the previous example), these objects may be made persistent in any order you like unless you have a NOT NULL constraint upon a foreign key column. There is never a risk of violating foreign key constraints. However, you might violate a NOT NULL constraint if you save() the objects in the wrong order.
永続化するオブジェクトが関連オブジェクトを持っている場合 (例えば、前の例におけるkittensコレクションのように)、 外部キーカラムに、NOT NULL制約をつけない限りは、 これらの一連のオブジェクトをどんな順番で永続化してもかまいません。外部キー制約を違反する恐れはありません。 しかし、NOT NULL制約がある場合、間違った順番でオブジェクトをsave()してしまうと、制約に違反するかもしれません。
Usually you don't bother with this detail, as you'll very likely use Hibernate's transitive persistence feature to save the associated objects automatically. Then, even NOT NULLconstraint violations don't occur - Hibernate will take care of everything. Transitive persistence is discussed later in this chapter.
関連するオブジェクトを自動的に保存する、 Hibernateの遷移的な永続化(transitive persistence)機能を 使うつもりならば、そのような詳細を気にする必要はありません。そして、NOT NULL制約の違反すら起こりません。Hibernateがすべて面倒をみてくれます。遷移的な永続化は、この章の後半に書かれています。
10.3. Loading an object(オブジェクトのロード)
The load() methods of Session gives you a way to retrieve a persistent instance if you already know its identifier. load() takes a class object and will load the state into a newly instantiated instance of that class, in persistent state.
永続化されたインスタンスの識別子があらかじめ分かっているなら、Sessionload()メソッドを使って、復元できます。load()は、Class オブジェクトを引数にとり、 そのクラスのインスタンスを新たに生成し、状態をロードします。そのインスタンスの状態は、永続(persistent)状態です
Cat fritz = (Cat) sess.load(Cat.class, generatedId);
// you need to wrap primitive identifiers
long id = 1234;
DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id) );
Alternatively, you can load state into a given instance:
あるいは、以下のように、既存のインスタンスに状態をロードすることも出来ます。
Cat cat = new DomesticCat();
// load pk's state into cat
sess.load( cat, new Long(pkId) );
Set kittens = cat.getKittens();
Note that load() will throw an unrecoverable exception if there is no matching database row. If the class is mapped with a proxy, load() just returns an uninitialized proxy and does not actually hit the database until you invoke a method of the proxy. This behaviour is very useful if you wish to create an association to an object without actually loading it from the database. It also allows multiple instances to be loaded as a batch if batch-size is defined for the class mapping.
DBに該当する行が無い場合、load()は回復不可能な例外を 投げることに注意しましょう。そのクラスがプロキシを使ってマッピングされている場合、load()は初期化されていないプロキシを返し、プロキシのメソッドが呼ばれるまで実際には データベースにアクセスしません。もし、実際にデータベースからロードせずに、オブジェクトに対する関連を作りたい場合、 この振る舞いはとても役立ちます。batch-sizeがクラスマッピングに定義されているならば、複数のインスタンスを一括でロードすることが可能です。
If you are not certain that a matching row exists, you should use the get() method, which hits the database immediately and returns null if there is no matching row.
該当する行が存在することを確信できない場合は、get()メソッドを使うべきです。それは、データベースにすぐにアクセスし、該当する行が無い場合はnullを返します。
Cat cat = (Cat) sess.get(Cat.class, id);
if (cat==null) {
    cat = new Cat();
    sess.save(cat, id);
}
return cat;
You may even load an object using an SQL SELECT ... FOR UPDATE, using a LockMode. See the API documentation for more information.
LockModeを使えば、SELECT ... FOR UPDATEというSQL 使ってオブジェクトをロードすることができます。詳細な情報は、APIドキュメントを参照してください。
Cat cat = (Cat) sess.get(Cat.class, id, LockMode.UPGRADE);
Note that any associated instances or contained collections are not selected FOR UPDATE, unless you decide to specify lock or all as a cascade style for the association.
関連に対するカスケード方法としてlockallを指定しない限り、関連するインスタンスや含まれるコレクションはFOR UPDATEで復元されないことに注意しましょう。
It is possible to re-load an object and all its collections at any time, using the refresh()method. This is useful when database triggers are used to initialize some of the properties of the object.
refresh()メソッドを使うことで、どんなときでも、オブジェクトやそのコレクションをリロードすることができます。 データベースのトリガがテーブルを更新した際に、そのテーブルに対応するオブジェクトのプロパティを同期する場合、このメソッドが役に立ちます。
sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
An important question usually appears at this point: How much does Hibernate load from the database and how many SQL SELECTs will it use? This depends on the fetching strategy and is explained in Section 19.1, "Fetching strategies".
大切な問題は、いつも次の点に関するものです。それは、Hibernateがデータベースから、どのくらいの量を復元するのかと、どのくらいの数のSQLSELECT文が使われるのかです。これは、フェッチの戦略によります。これについては、Section 19.1, "Fetching strategies"で説明しています。
10.4. Querying(クエリ)
If you don't know the identifiers of the objects you are looking for, you need a query. Hibernate supports an easy-to-use but powerful object oriented query language (HQL). For programmatic query creation, Hibernate supports a sophisticated Criteria and Example query feature (QBC and QBE). You may also express your query in the native SQL of your database, with optional support from Hibernate for result set conversion into objects.
探したいオブジェクトの識別子が分からない場合は、クエリが必要になります。Hibernateは使いやすくて強力なオブジェクト指向のクエリ言語 (HQL)をサポートしています。プログラムによってクエリが作成できるように、Hibernateは洗練されたCriteriaExampleクエリ機能(QBCQBE)をサポートしています。ResultSetをオブジェクトに変換するHibernateのオプション機能を使うことで、データベースのネイティブなSQLでクエリを表現することもできます。
10.4.1. Executing queries(クエリの実行)
HQL and native SQL queries are represented with an instance of org.hibernate.Query. This interface offers methods for parameter binding, result set handling, and for the execution of the actual query. You always obtain a Query using the current Session:
HQLやネイティブなSQLクエリは、org.hibernate.Queryのインスタンスとして表現されます。 このインタフェースは、パラメータバインディングやResultSetのハンドリングやクエリの実行を行うメソッドを用意しています。 通常、Queryは、以下に示すように、その時点のSessionを使って取得します。
List cats = session.createQuery(
    "from Cat as cat where cat.birthdate < ?")
    .setDate(0, date)
    .list();

List mothers = session.createQuery(
    "select mother from Cat as cat join cat.mother as mother where cat.name = ?")
    .setString(0, name)
    .list();

List kittens = session.createQuery(
    "from Cat as cat where cat.mother = ?")
    .setEntity(0, pk)
    .list();

Cat mother = (Cat) session.createQuery(
    "select cat.mother from Cat as cat where cat = ?")
    .setEntity(0, izi)
    .uniqueResult();]]

Query mothersWithKittens = (Cat) session.createQuery(
    "select mother from Cat as mother left join fetch mother.kittens");
Set uniqueMothers = new HashSet(mothersWithKittens.list());
A query is usually executed by invoking list(), the result of the query will be loaded completely into a collection in memory. Entity instances retrieved by a query are in persistent state. The uniqueResult() method offers a shortcut if you know your query will only return a single object. Note that queries that make use of eager fetching of collections usually return duplicates of the root objects (but with their collections initialized). You can filter these duplicates simply through a Set.
クエリは、普通、list()を呼び出すことによって実行されます。クエリの結果は、メモリ上にあるコレクションにすべてロードされます。クエリによって復元されたエンティティのインスタンスは、永続状態です。もし、クエリがたった1個のインスタンスを返すと分かっているなら、uniqueResult()メソッドが手っ取り早い方法です。即時フェッチを利用したクエリの場合、ふつう、得られたコレクションには、ルートのオブジェクトが重複して含まれています(しかし、ルートが持つコレクションは初期化(ロード)されています)。 この重複はSetを使って取り除くことができます。
10.4.1.1. Iterating results(結果を反復する)
Occasionally, you might be able to achieve better performance by executing the query using the iterate() method. This will only usually be the case if you expect that the actual entity instances returned by the query will already be in the session or second-level cache. If they are not already cached, iterate() will be slower than list() and might require many database hits for a simple query, usually 1 for the initial select which only returns identifiers, and n additional selects to initialize the actual instances.
時々、iterate()メソッドを使ってクエリを実行することで、より良いパフォーマンスを得ることができます。 これは、通常、クエリによって得られた実際のエンティティのインスタンスが、すでにセッションまたは二次キャッシュに存在することが期待できる場合だけです。それらが、まだキャッシュされていないなら、iterate()は、list()よりも遅く、簡単なクエリに対しても多くのデータベースアクセスを必要とします。そのアクセスとは、識別子だけを取得するための最初のselect1回と、実際のインスタンスを初期化するために後から行うn回のselectのことです。
// fetch ids
Iterator iter = sess.createQuery("from eg.Qux q order by q.likeliness").iterate();
while ( iter.hasNext() ) {
    Qux qux = (Qux) iter.next();  // fetch the object
    // something we couldnt express in the query
    if ( qux.calculateComplicatedAlgorithm() ) {
        // delete the current instance
        iter.remove();
        // dont need to process the rest
        break;
    }
}
10.4.1.2. Queries that return tuples(制限されたシーケンスを返すクエリ)
Hibernate queries sometimes return tuples of objects, in which case each tuple is returned as an array:
Hibernateのクエリでは、時々、オブジェクトの制限されたシーケンスを返すことがあります。 その場合は、各タプルは配列として返されます。
Iterator kittensAndMothers = sess.createQuery(
            "select kitten, mother from Cat kitten join kitten.mother mother")
            .list()
            .iterator();

while ( kittensAndMothers.hasNext() ) {
    Object[] tuple = (Object[]) kittensAndMothers.next();
    Cat kitten  = tuple[0];
    Cat mother  = tuple[1];
    ....
}
10.4.1.3. Scalar results(スカラーの結果)
Queries may specify a property of a class in the select clause. They may even call SQL aggregate functions. Properties or aggregates are considered "scalar" results (and not entities in persistent state).
クエリでは、select節でクラスのプロパティを指定できます。SQLの集合関数を呼ぶこともできます。プロパティや集合関数は、(永続状態のエンティティではなく)「スカラー値」であると見なされます。
Iterator results = sess.createQuery(
        "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
        "group by cat.color")
        .list()
        .iterator();

while ( results.hasNext() ) {
    Object[] row = (Object[]) results.next();
    Color type = (Color) row[0];
    Date oldest = (Date) row[1];
    Integer count = (Integer) row[2];
    .....
}
10.4.1.4. Bind parameters(パラメータのバインド)
Methods on Query are provided for binding values to named parameters or JDBC-style ?parameters. Contrary to JDBC, Hibernate numbers parameters from zero. Named parameters are identifiers of the form :name in the query string. The advantages of named parameters are:
Queryは、名前付きのパラメータやJDBCスタイルの?パラメータに値をバインドするためのメソッドを持っています。JDBCとは違い、Hibernateはパラメータにゼロから番号を振っていきます。名前付きのパラメータとは、クエリ文字列のなかにある:name形式の識別子です。名前付きパラメータの利点は次の通りです。
?         named parameters are insensitive to the order they occur in the query string
名前付きパラメータは、クエリ文字列に登場する順番と無関係です
?         they may occur multiple times in the same query
同じクエリ内に複数回登場することができます
?         they are self-documenting
自分自身を説明します。
//named parameter (preferred)
Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
q.setString("name", "Fritz");
Iterator cats = q.iterate();
//positional parameter
Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
q.setString(0, "Izi");
Iterator cats = q.iterate();
//named parameter list
List names = new ArrayList();
names.add("Izi");
names.add("Fritz");
Query q = sess.createQuery("from DomesticCat cat where cat.name in (:namesList)");
q.setParameterList("namesList", names);
List cats = q.list();
10.4.1.5. Pagination(ページ分け)
If you need to specify bounds upon your result set (the maximum number of rows you want to retrieve and / or the first row you want to retrieve) you should use methods of the Query interface:
ResultSetに制限(復元したい最大行数や復元したい最初の行)を加える必要があれば、以下のように、Queryインタフェースのメソッドを使います。
Query q = sess.createQuery("from DomesticCat cat");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.list();
Hibernate knows how to translate this limit query into the native SQL of your DBMS.
制限付きのクエリをDBMSのネイティブなSQLに変換する方法を、Hibernateは知っています。
10.4.1.6. Scrollable iteration(スクロール可能なイテレーション)
If your JDBC driver supports scrollable ResultSets, the Query interface may be used to obtain a ScrollableResults object, which allows flexible navigation of the query results.
JDBCドライバがスクロール可能なResultSetをサポートしていれば、Queryインタフェースを使って、ScrollableResultsオブジェクトを取得できます。それを使うと、クエリの結果に対して柔軟にナビゲーションできます。
Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +
                            "order by cat.name");
ScrollableResults cats = q.scroll();
if ( cats.first() ) {

    // find the first name on each page of an alphabetical list of cats by name
    firstNamesOfPages = new ArrayList();
    do {
        String name = cats.getString(0);
        firstNamesOfPages.add(name);
    }
    while ( cats.scroll(PAGE_SIZE) );

    // Now get the first page of cats
    pageOfCats = new ArrayList();
    cats.beforeFirst();
    int i=0;
    while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1) );

}
cats.close()
Note that an open database connection (and cursor) is required for this functionality, usesetMaxResult()/setFirstResult() if you need offline pagination functionality.
この機能にはオープン状態のデータベースコネクションが必要であることに注意してください。もし、オフラインのページ分け機能が必要であれば、setMaxResult()/setFirstResult()を使いましょう。
10.4.1.7. Externalizing named queries(名前つきクエリの外出し)
You may also define named queries in the mapping document. (Remember to use aCDATA section if your query contains characters that could be interpreted as markup.)
マッピングドキュメントに名前付きのクエリを定義することができます。(マークアップと解釈される文字がクエリに含まれるなら、CDATAセクションを使うことを忘れないようにしましょう。)
<query name="ByNameAndMaximumWeight"><![CDATA[
    from eg.DomesticCat as cat
        where cat.name = ?
        and cat.weight > ?
] ]></query>
Parameter binding and executing is done programatically:
パラメータのバインディングと実行は、以下のようなプログラムで行われます。
Query q = sess.getNamedQuery("ByNameAndMaximumWeight");
q.setString(0, name);
q.setInt(1, minWeight);
List cats = q.list();
Note that the actual program code is independent of the query language that is used, you may also define native SQL queries in metadata, or migrate existing queries to Hibernate by placing them in mapping files.
実際のプログラムコードは、使われるクエリ言語に依存していないことに注意しましょう。メタデータには、ネイティブSQLクエリを定義することもできます。 また、既存のクエリをマッピングファイルに移すことで、Hibernateに移行することもできます。
Also note that a query declaration inside a <hibernate-mapping> element requires a global unique name for the query, while a query declaration inside a <class> element is made unique automatically by prepending the fully qualified name of the class, for example eg.Cat.ByNameAndMaximumWeight.
<hibernate-mapping>の中のクエリ定義は、クエリに対するユニークな名前が必要なことにも注意してください。それに対して、<class>の中のクエリ定義は、クラスの完全限定名が前に付けられるので、自動的にユニークな名前になります。例:eg.Cat.ByNameAndMaximumWeight
10.4.2. Filtering collections(コレクションのフィルタリング)
A collection filter is a special type of query that may be applied to a persistent collection or array. The query string may refer to this, meaning the current collection element.
コレクションフィルタは、永続化されているコレクションや配列に適用される特殊なタイプのクエリです。そのクエリ文字列では、コレクションのその時点での要素を意味するthisを使います。
Collection blackKittens = session.createFilter(
    pk.getKittens(), 
    "where this.color = ?")
    .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) )
    .list()
);
The returned collection is considered a bag, and it's a copy of the given collection. The original collection is not modified (this is contrary to the implication of the name "filter", but consistent with expected behavior).
返されるコレクションはBagとみなされます。そして、それはもとのコレクションのコピーになります。元のコレクションは修正されません(これは、"filter"という名前の意味とは異なりますが、 期待される動きとは一致しています)。
Observe that filters do not require a from clause (though they may have one if required). Filters are not limited to returning the collection elements themselves.
フィルタにはfrom節が不要であることに気づくでしょう(必要なら、持つことも可能ですが)。 フィルタは、コレクションの要素自体を返して構いません。
Collection blackKittenMates = session.createFilter(
    pk.getKittens(), 
    "select this.mate where this.color = eg.Color.BLACK.intValue")
    .list();
Even an empty filter query is useful, e.g. to load a subset of elements in a huge collection:
クエリを含まないフィルタも役に立ちます。例えば、非常に大きなコレクションの部分集合をロードするために使えます。
Collection tenKittens = session.createFilter(
    mother.getKittens(), "")
    .setFirstResult(0).setMaxResults(10)
    .list();
10.4.3. Criteria queries(クライテリアのクエリ)
HQL is extremely powerful but some developers prefer to build queries dynamically, using an object-oriented API, rather than building query strings. Hibernate provides an intuitive Criteria query API for these cases:
HQLは非常に強力ですが、クエリ文字列を作るよりも、オブジェクト指向のAPIを使って動的にクエリを作る方を好む開発者もいます。 こういった場合のために、Hibernateは直感的なCriteriaクエリAPIを提供しています。
Criteria crit = session.createCriteria(Cat.class);
crit.add( Expression.eq( "color", eg.Color.BLACK ) );
crit.setMaxResults(10);
List cats = crit.list();
The Criteria and the associated Example API are discussed in more detail in Chapter 15,Criteria Queries.
ExampleAPIの詳細は、 Chapter 15, Criteria Queriesに述べられています。
10.4.4. Queries in native SQL(ネイティブSQLクエリ)
You may express a query in SQL, using createSQLQuery() and let Hibernate take care of the mapping from result sets to objects. Note that you may at any time callsession.connection() and use the JDBC Connection directly. If you chose to use the Hibernate API, you must enclose SQL aliases in braces:
createSQLQuery()を使って、SQLでクエリを表現することもできます。そして、Hibernateに、ResultSet からオブジェクトへのマッピングをまかせます。session.connection()を呼べばどんなときでも、直接、JDBC Connectionを使用できることを覚えておきましょう。 もし、HibernateAPIを使うのであれば、下記のようにSQLの別名を括弧でくくらなければなりません。
List cats = session.createSQLQuery(
    "SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10",
    "cat",
    Cat.class
).list();
List cats = session.createSQLQuery(
    "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
           "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
    "FROM CAT {cat} WHERE ROWNUM<10",
    "cat",
    Cat.class
).list()
SQL queries may contain named and positional parameters, just like Hibernate queries. More information about native SQL queries in Hibernate can be found in Chapter 16,Native SQL.
SQLクエリは、Hibernateクエリと同じように、名前付きのパラメータと位置パラメータを持つことができます。HibernateにおけるネイティブなSQLクエリの詳細については、Chapter 16, Native SQLを参照してください。
10.5. Modifying persistent objects(永続オブジェクトの修正)
Transactional persistent instances (ie. objects loaded, saved, created or queried by theSession) may be manipulated by the application and any changes to persistent state will be persisted when the Session is flushed (discussed later in this chapter). There is no need to call a particular method (like update(), which has a different purpose) to make your modifications persistent. So the most straightforward way to update the state of an object is to load() it, and then manipulate it directly, while the Session is open:
処理中の永続インスタンス(例:Sessionによって、ロード、セーブ、クエリ、作成されたオブジェクト)は、アプリケーションに操作されます。その際に変更された永続状態は、Sessionがフラッシュされるときに、永続化されます(これは、この章の後半で述べています)。変更を永続化するために、特殊なメソッド(update()のようなもの。これは、別の目的で使用します)を 呼ぶ必要はありません。 オブジェクトの状態を更新する一番簡単な方法は、オブジェクトをload()し、Sessionをオープンにしている間に、直接操作することです。
DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
cat.setName("PK");
sess.flush();  // changes to cat are automatically detected and persisted
Sometimes this programming model is inefficient since it would require both an SQLSELECT (to load an object) and an SQL UPDATE (to persist its updated state) in the same session. Therefore Hibernate offers an alternate approach, using detached instances.
(オブジェクトをロードするための)SQLSELECTと(更新された状態を永続化するための)SQLUPDATEが同じセッションで必要となるので、このプログラミングモデルは、効率が悪くなる場合があります。そのため、Hibernateは別の方法を用意しています。それは、インスタンスを分離する(detached)方法です。
Note that Hibernate does not offer its own API for direct execution of UPDATE orDELETE statements. Hibernate is a state management service, you don't have to think in statements to use it. JDBC is a perfect API for executing SQL statements, you can get a JDBC Connection at any time by calling session.connection(). Furthermore, the notion of mass operations conflicts with object/relational mapping for online transaction processing-oriented applications. Future versions of Hibernate may however provide special mass operation functions. See Chapter 13, Batch processing for some possible batch operation tricks.
Hibernateは、UPDATE文やDELETE文を直接実行するAPIを用意していません。Hibernateは、状態管理サービスであり、使われるSQL文のことを開発者が考える必要はありません。JDBCSQL文を実行する完璧なAPIであり、session.connection() を呼ぶことで いつでも、JDBCConnectionを開発者は取得できます。さらに、大量のデータ操作の考え方は、オンライントランザクション処理向きアプリケーションのオブジェクト/リレーショナルマッピングと衝突します。しかし、Hibernateの今後のバージョンでは、大量データを処理する特別な機能を提供するかもしれません。バッチ操作に利用できるいくつかの工夫については、Chapter 13, Batch processingを参照してください。
10.6. Modifying detached objects(分離オブジェクトの修正)
Many applications need to retrieve an object in one transaction, send it to the UI layer for manipulation, then save the changes in a new transaction. Applications that use this kind of approach in a high-concurrency environment usually use versioned data to ensure isolation for the "long" unit of work.
多くのアプリケーションでは次のことが必要になります。それは、あるトランザクションでオブジェクトを復元し、操作するためにそれをUI層に送り、その後に、新しいトランザクションで変更をセーブするといったことです。並行性の高い環境で、このタイプのアプローチを使うアプリケーションでは、 "期間の長い"作業単位の隔離性を保証するために、バージョンデータが通常使われます。
Hibernate supports this model by providing for reattachment of detached instances using the Session.update() or Session.merge() methods:
Hibernateは、Session.update()Session.merge()メソッドを使って、分離インスタンスを再追加することで、このモデルに対応します。
// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher layer of the application
cat.setMate(potentialMate);

// later, in a new session
secondSession.update(cat);  // update cat
secondSession.update(mate); // update mate
If the Cat with identifier catId had already been loaded by secondSession when the application tried to reattach it, an exception would have been thrown.
識別子catIdを持つCatが、既にsecondSessionでロードされていた場合は、再追加しようとしたときに、例外が投げられます。
Use update() if you are sure that the session does not contain an already persistent instance with the same identifier, and merge() if you want to merge your modifications at any time without consideration of the state of the session. In other words, update() is usually the first method you would call in a fresh session, ensuring that reattachment of your detached instances is the first operation that is executed.
同じ識別子を持つ永続インスタンスをセッションが既に保持していないことを確信できるならupdate()を使いましょう。そして、セッションの状態を考えずに、どんな場合でも変更をマージしたい場合は、merge()を使いましょう。 すなわち、分離オブジェクトの再追加操作が、最初に実行されることを確実にするために、 通常はupdate()が新しいセッションのなかで最初に呼ばれるメソッドになります。
The application should individually update() detached instances reachable from the given detached instance if and only if it wants their state also updated. This can be automated of course, using transitive persistence, see Section 10.11, "Transitive persistence".
分離インスタンスから到達可能な、分離インスタンスをアプリケーションは個別にupdate()すべきです。それは、その状態を更新したい場合に限ります。遷移的な永続化を使えば、もちろん自動化できます。Section 10.11, "Transitive persistence"を参照してください。
The lock() method also allows an application to reassociate an object with a new session. However, the detached instance has to be unmodified!
メソッドでもまた、新しいセッションにオブジェクトを再関連付けできます。 しかし、分離インスタンスは無修正でなければなりません。
//just reassociate:
sess.lock(fritz, LockMode.NONE);
//do a version check, then reassociate:
sess.lock(izi, LockMode.READ);
//do a version check, using SELECT ... FOR UPDATE, then reassociate:
sess.lock(pk, LockMode.UPGRADE);
Note that lock() can be used with various LockModes, see the API documentation and the chapter on transaction handling for more information. Reattachment is not the only usecase for lock().
lock()は、さまざまなLockModeとともに使うことができます。詳細は、APIドキュメントとトランザクション処理の章を参照してください。再追加のときにだけ、lock()が使われるわけではありません。
Other models for long units of work are discussed in Section 11.3, "Optimistic concurrency control".
期間の長い作業単位の、その他のモデルは、Section 11.3, "Optimistic concurrency control"で述べています。
10.7. Automatic state detection(自動的な状態検出)
Hibernate users have requested a general purpose method that either saves a transient instance by generating a new identifier or updates/reattaches the detached instances associated with its current identifier. The saveOrUpdate() method implements this functionality.
Hibernateのユーザは次の2つのケースのどちらにも使える汎用的なメソッドを要求していました。それは、新しい識別子を生成して一時的なインスタンスをセーブすることと、その時点の識別子と関連づいている分離インスタンスを更新/再追加することのできるメソッドです。saveOrUpdate()はこのような機能を実現したメソッドです。
// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catID);

// in a higher tier of the application
Cat mate = new Cat();
cat.setMate(mate);

// later, in a new session
secondSession.saveOrUpdate(cat);   // update existing state (cat has a non-null id)
secondSession.saveOrUpdate(mate);  // save the new instance (mate has a null id)
The usage and semantics of saveOrUpdate() seems to be confusing for new users. Firstly, so long as you are not trying to use instances from one session in another new session, you should not need to use update()saveOrUpdate(), or merge(). Some whole applications will never use either of these methods.
saveOrUpdate()の使用方法と意味は、新しいユーザにとって混乱を招くかもしれません。まず第一に、あるセッションで使用したインスタンスを別の新しいセッションで使おうとしない限り、update()saveOrUpdate()merge()を使う必要はありません。アプリケーション全体を通じて、これらのメソッドを全く使わないこともあります。
Usually update() or saveOrUpdate() are used in the following scenario:
通常、update()saveOrUpdate()は次のシナリオで使われます。
?         the application loads an object in the first session
アプリケーションは最初のセッションにオブジェクトをロードするとき。
?         the object is passed up to the UI tier
オブジェクトがUI層に送られたとき。
?         some modifications are made to the object
オブジェクトに対して変更が加えられたとき。
?         the object is passed back down to the business logic tier
オブジェクトがビジネスロジック層に送られたとき
?         the application persists these modifications by calling update() in a second session
アプリケーションは、2番目のセッションでupdate()を呼ぶことで、これらの変更を永続化されたとき。
saveOrUpdate() does the following:
saveOrUpdate()は以下のことを行います。
?         if the object is already persistent in this session, do nothing
オブジェクトがこのセッションで、すでに永続化されていれば、何もしません。
?         if another object associated with the session has the same identifier, throw an exception
そのセッションに関連づいている別のオブジェクトが同じ識別子を持っているなら、 例外を投げます。
?         if the object has no identifier property, save() it
オブジェクトの識別子が値を持たないならば、save()します。
?         if the object's identifier has the value assigned to a newly instantiated object,save() it
オブジェクトの識別子が値を持ち、その値が新たにインスタンス化されたオブジェクトのための値である場合、 そのオブジェクトをsave()します。
?         if the object is versioned (by a <version> or <timestamp>), and the version property value is the same value assigned to a newly instantiated object, save() it
オブジェクトが(<version><timestamp>によって)バージョンづけされていて、バージョンのプロパティが値を持ち、その値が新しくインスタンス化されたオブジェクトのための値である場合、 そのオブジェクトをsave()します。
?         otherwise update() the object
そうでない場合は、そのオブジェクトをupdate()します。
and merge() is very different:
そして、merge()は以下のようにとても異なります。
?         if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
同じ識別子を持つ永続化インスタンスがその時点でセッションと関連付いているならば、引数で受け取ったオブジェクトの状態を永続化インスタンスにコピーします。
?         if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
永続化インスタンスがその時点でセッションに関連付いていないなら、データベースからそれをロードするか、あるいは、新しい永続化インスタンスを作成します。
?         the persistent instance is returned
永続化インスタンスが返されます。
?         the given instance does not become associated with the session, it remains detached
引数として与えたインスタンスはセッションと関連を持ちません。 それは、分離状態のままです。
10.8. Deleting persistent objects(永続オブジェクトの削除)
Session.delete() will remove an object's state from the database. Of course, your application might still hold a reference to a deleted object. It's best to think of delete()as making a persistent instance transient.
Session.delete()はオブジェクトの状態をデータベースから削除します。 もちろん、削除したオブジェクトをアプリケーションが保持したままでもよいです。そのため、delete()は永続インスタンスを一時的にするものと考えるのが一番です。
sess.delete(cat);
You may delete objects in any order you like, without risk of foreign key constraint violations. It is still possible to violate a NOT NULL constraint on a foreign key column by deleting objects in the wrong order, e.g. if you delete the parent, but forget to delete the children.
外部キー制約に違反するリスクもなく、好きな順番でオブジェクトを削除することができます。ただし、間違った順番でオブジェクトを削除すると、外部キーカラムのNOT NULL制約に違反する可能性があります。 例えば、親オブジェクトを削除したときに、子供オブジェクトを削除し忘れた場合です。
10.9. Replicating object between two different datastores(異なる二つのデータストア間でのオブジェクトのレプリケーション)
It is occasionally useful to be able to take a graph of persistent instances and make them persistent in a different datastore, without regenerating identifier values.
永続インスタンスのグラフを別のデータストアに永続化する場合に、識別子の値を再生成せずにすむと便利な場合があります。
//retrieve a cat from one database
Session session1 = factory1.openSession();
Transaction tx1 = session1.beginTransaction();
Cat cat = session1.get(Cat.class, catId);
tx1.commit();
session1.close();

//reconcile with a second database
Session session2 = factory2.openSession();
Transaction tx2 = session2.beginTransaction();
session2.replicate(cat, ReplicationMode.LATEST_VERSION);
tx2.commit();
session2.close();
The ReplicationMode determines how replicate() will deal with conflicts with existing rows in the database.
レプリケーション先のデータベースに行が既にある場合、replicate()が衝突をどのように扱うかをReplicationModeで指定します。
?         ReplicationMode.IGNORE - ignore the object when there is an existing database row with the same identifier
ReplicationMode.IGNORE-同じ識別子を持つ行がデータベースに存在するなら、 そのオブジェクトを無視します。
?         ReplicationMode.OVERWRITE - overwrite any existing database row with the same identifier
ReplicationMode.OVERWRITE- 同じ識別子を持つ既存の行をすべて上書きします。
?         ReplicationMode.EXCEPTION - throw an exception if there is an existing database row with the same identifier
ReplicationMode.EXCEPTION-同じ識別子を持つ行がデータベースに存在するなら、 例外を投げます。
?         ReplicationMode.LATEST_VERSION - overwrite the row if its version number is earlier than the version number of the object, or ignore the object otherwise
ReplicationMode.LATEST_VERSION-行に保存されているバージョン番号が、 引数のオブジェクトのバージョン番号より古いならば、その行を上書きします。
Usecases for this feature include reconciling data entered into different database instances, upgrading system configuration information during product upgrades, rolling back changes made during non-ACID transactions and more.
次のようなケースで、この機能を使用します。 異なるデータベースインスタンスに入れられたデータの同期、製品更新時におけるシステム設定情報の更新、非ACIDトランザクションのなかで加えられた変更のロールバックなどです。
10.10. Flushing the Session(セッションのフラッシュ)
From time to time the Session will execute the SQL statements needed to synchronize the JDBC connection's state with the state of objects held in memory. This process,flush, occurs by default at the following points
JDBCコネクションの状態とメモリ上のオブジェクトの状態を同期させるために必要なSQL文をSessionが実行することがときどきあります。 この処理flushは、デフォルトでは次のときに起こります。
?         before some query executions
クエリを実行する前
?         from org.hibernate.Transaction.commit()
org.hibernate.Transaction.commit()を実行したとき
?         from Session.flush()
Session.flush()を実行したとき
The SQL statements are issued in the following order
SQL文は以下の順番で発行されます。
1.      all entity insertions, in the same order the corresponding objects were saved usingSession.save()
すべてのエンティティの挿入。これは、Session.save()を使ってセーブしたオブジェクトの順に実行していきます。
2.      all entity updates
すべてのエンティティの更新
3.      all collection deletions
すべてのコレクションの削除
4.      all collection element deletions, updates and insertions
すべてのコレクションの要素に対する削除、更新、挿入
5.      all collection insertions
すべてのコレクションの挿入
6.      all entity deletions, in the same order the corresponding objects were deleted using Session.delete()
すべてのエンティティの削除。これは、Session.delete()を使って削除したオブジェクトの順に実行していきます。
(An exception is that objects using native ID generation are inserted when they are saved.)
(1つ例外があります。nativeID 生成を使ったオブジェクトは、それらがセーブされたときに挿入されます。)
Except when you explicity flush(), there are absolutely no guarantees about when theSession executes the JDBC calls, only the order in which they are executed. However, Hibernate does guarantee that the Query.list(..) will never return stale data; nor will they return the wrong data.
明示的にflush()するときを除いて、いつSessionJDBCをコールするのかについて絶対的な保証はありません。ただし、それらが実行される順番だけは 保証されます。また、Hibernate は、Query.list(..)が古いデータや間違ったデータ返さないことを保証しています。
It is possible to change the default behavior so that flush occurs less frequently. TheFlushMode class defines three different modes: only flush at commit time (and only when the Hibernate Transaction API is used), flush automatically using the explained routine, or never flush unless flush() is called explicitly. The last mode is useful for long running units of work, where a Session is kept open and disconnected for a long time (see Section 11.3.2, "Extended session and automatic versioning").
フラッシュが頻繁に起こらないようにデフォルトの振る舞いを変えることができます。FlushModeクラスは3つの異なるモードを定義します。 それは、コミット時にだけフラッシュするモード HibernateTransactionAPIが使われる場合だけです)、説明のあった処理順に基づいて自動でフラッシュするモード、flush()が明示的に呼ばれない限りフラッシュしないモードの3つです。 最後のモードは、作業単位が長期間に及ぶ場合に役に立ちます (Section 11.3.2, "Extended session and automatic versioning"を参照してください)
sess = sf.openSession();
Transaction tx = sess.beginTransaction();
sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state

Cat izi = (Cat) sess.load(Cat.class, id);
izi.setName(iznizi);

// might return stale data
sess.find("from Cat as cat left outer join cat.kittens kitten");

// change to izi is not flushed!
...
tx.commit(); // flush occurs
sess.close();
During flush, an exception might occur (e.g. if a DML operation violates a constraint). Since handling exceptions involves some understanding of Hibernate's transactional behavior, we discuss it in Chapter 11, Transactions And Concurrency.
フラッシュのとき、例外が発生するかもしれません。(例えば、DML操作が制約を違反するような場合です。)例外処理を理解するためには、Hibernateのトランザクションの振る舞いを理解する必要があるため、 Chapter 11, Transactions And Concurrencyで説明します。
10.11. Transitive persistence(連鎖的な永続化)
It is quite cumbersome to save, delete, or reattach individual objects, especially if you deal with a graph of associated objects. A common case is a parent/child relationship. Consider the following example:
個々のオブジェクトをセーブしたり、削除したり、再追加したりすることはかなり面倒です。特に、関連するオブジェクトを扱うような場合には際立ちます。 よくあるのは、親子関係を扱うケースです。以下の例を考えてみましょう。
If the children in a parent/child relationship would be value typed (e.g. a collection of addresses or strings), their lifecycle would depend on the parent and no further action would be required for convenient "cascading" of state changes. When the parent is saved, the value-typed child objects are saved as well, when the parent is deleted, the children will be deleted, etc. This even works for operations such as the removal of a child from the collection; Hibernate will detect this and, since value-typed objects can't have shared references, delete the child from the database.
もし、親子関係の子が値型なら(例えば、住所や文字列のコレクション)、それらのライフサイクルは親に依存しており、便利な状態変化の"カスケード"を使うために、 追加の作業は必要はありません。親がセーブされたとき、値型の子オブジェクトも同じようにセーブされますし、 親が削除されたときは、子も削除されます。その他の操作も同じです。コレクションから1つの子を削除するような操作でもうまくいきます。 すなわち、Hibernateはこの削除操作を検出すると、値型のオブジェクトは参照を共有できないので、データベースからその子供を削除します。
Now consider the same scenario with parent and child objects being entities, not value-types (e.g. categories and items, or parent and child cats). Entities have their own lifecycle, support shared references (so removing an entity from the collection does not mean it can be deleted), and there is by default no cascading of state from one entity to any other associated entities. Hibernate does not implement persistence by reachabilityby default.
ここで、親と子が値型でなくエンティティであるとして同じシナリオを考えてみましょう。(例えば、カテゴリーと品目の関係や親と子の猫の関係です。) エンティティは、それ自身がライフサイクルを持ち、参照の共有をサポートします。(そのため、コレクションからエンティティを削除することは、 エンティティ自身の削除を意味しません。)また、エンティティは、デフォルトでは、関連する他のエンティティへ 状態をカスケードすることはありません。 Hibernateは到達可能性による永続化をデフォルトでは実行しません。
For each basic operation of the Hibernate session - including persist(), merge(), saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - there is a corresponding cascade style. Respectively, the cascade styles are named create, merge, save-update, delete, lock, refresh, evict, replicate. If you want an operation to be cascaded along an association, you must indicate that in the mapping document. For example:
HibernateSessionの基本操作(persist(), merge(), saveOrUpdate(),delete(), lock(), refresh(), evict(), replicate()が含まれます)に対して、それぞれに対応するカスケードスタイルがあります。 それぞれのカスケードスタイルには、create, merge,save-update, delete, lock, refresh, evict, replicateという名前がついています。 もし、関連に沿ってカスケードさせたい操作があるなら、マッピングファイルにそう指定しなければなりません。例えば、以下のようにします。
<one-to-one name="person" cascade="persist"/>
Cascade styles my be combined:
カスケードスタイルは、組み合わせることができます。
<one-to-one name="person" cascade="persist,delete,lock"/>
You may even use cascade="all" to specify that all operations should be cascaded along the association. The default cascade="none" specifies that no operations are to be cascaded.
すべての操作を関連に沿ってカスケードするよう指定するときは、cascade="all"を使います。デフォルトのcascade="none"は、どの操作もカスケードしないことを意味します。
A special cascade style, delete-orphan, applies only to one-to-many associations, and indicates that the delete() operation should be applied to any child object that is removed from the association.
特殊なカスケードスタイルdelete-orphanは、一対多関連にだけ 適用できます。これは、関連から削除された子供のオブジェクトに対して、delete()操作が適用されることを意味します。
Recommendations:
推奨
?         It doesn't usually make sense to enable cascade on a <many-to-one> or <many-to-many> association. Cascade is often useful for <one-to-one> and <one-to-many>associations.
普通、<many-to-one><many-to-many>関連に対しては、カスケードを設定する意味はありません。<one-to-one><one-to-many>関連に対しては、カスケードが役に立つことがあります。
?         If the child object's lifespan is bounded by the lifespan of the of the parent object make it a lifecycle object by specifying cascade="all,delete-orphan".
子供オブジェクトの寿命が親オブジェクトの寿命に制限を受けるならば、cascade="all,delete-orphan"を指定し、 子供オブジェクトをライフサイクルオブジェクトにします。
?         Otherwise, you might not need cascade at all. But if you think that you will often be working with the parent and children together in the same transaction, and you want to save yourself some typing, consider using cascade="persist,merge,save-update".
それ以外の場合は、カスケードはほとんど必要ないでしょう。しかし、同じトランザクションのなかで親と子が一緒に動作することが多いと思い、いくらかのコードを書く手間を省きたいのであれば、cascade="persist,merge,save-update"を使うことを考えましょう。
Mapping an association (either a single valued association, or a collection) withcascade="all" marks the association as a parent/child style relationship where save/update/delete of the parent results in save/update/delete of the child or children.
cascade="all"でマッピングした関連(単値関連やコレクション)は、親子スタイルの関連とマークされます。それは、親のセーブ/更新/削除が、子のセーブ/更新/削除を引き起こす関係のことです。
Futhermore, a mere reference to a child from a persistent parent will result in save/update of the child. This metaphor is incomplete, however. A child which becomes unreferenced by its parent is not automatically deleted, except in the case of a <one-to-many> association mapped with cascade="delete-orphan". The precise semantics of cascading operations for a parent/child relationship are as follows:
さらに、永続化された親が子を単に参照しているだけで、子のセーブ/更新を引き起こします。しかし、このメタファーは不完全です。親から参照されなくなった子は、自動的に削除されません。ただし、cascade="delete-orphan"でマッピングされた<one-to-many>関連を 除いてです。親子関係のカスケード操作の正確な意味は以下のようになります。
?         If a parent is passed to persist(), all children are passed to persist()
親がpersist()に渡されたならば、 すべての子はpersist()に渡されます。
?         If a parent is passed to merge(), all children are passed to merge()
merge()に渡されたならば、 すべての子はmerge()に渡されます。
?         If a parent is passed to save()update() or saveOrUpdate(), all children are passed to saveOrUpdate()
親がsave()update()saveOrUpdate()に渡されたならば、すべての子はsaveOrUpdate()に渡されます。
?         If a transient or detached child becomes referenced by a persistent parent, it is passed to saveOrUpdate()
一時的または分離状態の子が、永続化された親に参照されたならば、saveOrUpdate()に渡されます。
?         If a parent is deleted, all children are passed to delete()
親が削除されたならば、すべての子は、delete()に渡されます。
?         If a child is dereferenced by a persistent parent, nothing special happens - the application should explicitly delete the child if necessary - unless cascade="delete-orphan", in which case the "orphaned" child is deleted.
子が永続化された親から参照されなくなったときは、特に何も起こりません。よって、アプリケーションが必要であれば、明示的に削除する必要があります。ただし、cascade="delete-orphan"の場合を除きます。この場合、「親のない」子は削除されます。
Finally, note that cascading of operations can be applied to an object graph at call timeor at flush time. All operations, if enabled, are cascaded to associated entities reachable when the operation is executed. However, save-upate and delete-orphan are transitive for all associated entities reachable during flush of the Session.
最後に、操作のカスケードがオブジェクトグラフに適用されるのは、コールした時あるいは、flushした時であることに注意してください。すべての操作は、その操作が実行されたときに、到達可能な関連するエンティティに対してカスケードが可能ならカスケードします。しかし、save-upatedelete-orphanは、Sessionflushしている間に、 すべての到達可能な関連するエンティティに伝播します。
10.12. Using metadata(メタデータの使用)
Hibernate requires a very rich meta-level model of all entity and value types. From time to time, this model is very useful to the application itself. For example, the application might use Hibernate's metadata to implement a "smart" deep-copy algorithm that understands which objects should be copied (eg. mutable value types) and which should not (eg. immutable value types and, possibly, associated entities).
Hibernateは、すべてのエンティティと値型の非常にリッチなメタレベルのモデルを必要とします。ときどき、このモデルはアプリケーションにとってとても役に立ちます。例えば、アプリケーションは、Hibernateのメタデータを使って、"賢いディープコピーアルゴリズムを実装できるかもしません。そのアルゴリズムとは、どのオブジェクトがコピーされるべきか(例:可変の値型)やどのオブジェクトはコピーされないべきか(例:不変な値型や可能なら関連するエンティティ)を 判断できるものです。
Hibernate exposes metadata via the ClassMetadata and CollectionMetadata interfaces and the Type hierarchy. Instances of the metadata interfaces may be obtained from theSessionFactory.
HibernateClassMetadataCollectionMetadataインタフェースとType階層を通してメタデータを公開します。メタデータインターフェイスのインスタンスは、SessionFactoryから得られます。
Cat fritz = ......;
ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);

Object[] propertyValues = catMeta.getPropertyValues(fritz);
String[] propertyNames = catMeta.getPropertyNames();
Type[] propertyTypes = catMeta.getPropertyTypes();

// get a Map of all properties which are not collections or associations
Map namedValues = new HashMap();
for ( int i=0; i<propertyNames.length; i++ ) {
    if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType() ) {
        namedValues.put( propertyNames[i], propertyValues[i] );
    }
}

No comments:

Post a Comment