ヒベルナ学習の第16編
session contextと事務境界用current_session_context.class属性はcontext(session Factory.get CurrenntSession)を定義し、その値は:1、thread:ThreadLocalでSessionを管理し、Sessionを複数の操作で共有し、Sessionを繰り返し取得しないようにし、事務境界の呼び出しを制御する。この時、sessionはcloseはcloseできない。comitやrollbackは自動的にオフになります。Open session in view:作成(レンダリング)ページでsessionを開いてください。2,jta:JTA事務管理器があり、事務connection.release_mode:after_statement悲観ロックと楽観ロックはデータベースで実現されます。楽観ロックはバージョンとtimestampで実現されます。悲観的なロックは、レコードを読む時にロックし、記録を更新した後、ロックを解除し、他の人が関連操作を行うことができます。今回は問題があります。一人でデータを読み込んだらロックがかかりますが、操作を続けていないため、他の人も同じ記録を読みたい時は制限されています。前の人が操作してから行うしかないです。楽観的なロックは、バージョン番号とタイムスタンプの方式をとっています。例えば、2人ともデータ記録を読み込むことができます。それに応じて修正の提出が完了した場合、先に提出した問題はありません。(当時のデータのバージョン番号は修正されていません。提出後はバージョン番号が増加します。)後に提出するとバージョン番号の問題が発生します。先に提出したものはバージョン番号の更新につながりますので、新しいバージョン番号と後ほど提出したバージョン番号が一致しなくなり、後者のロールバックにつながります。これは後者にヒントを与えます。データは更新されたか、変更を放棄するか、または再読み込みして更新します。例コード:Userクラスのソースコードは以下の通りです。以前のコードとの違いは、バージョン属性Public class Userを追加しました。 prvate int id prvate Name userName; prvate Date bithday; privte int version;}マッピングファイルの配置も相応の修正を行う必要があります。 テストコード:
印刷出力のsql文は、ハイバーナ:insert into user(version、first uname、lastuuname、birthday)values(?、?、?)Hberra:select user 0_.id as id 0_0_、アメリカ.version as version 0_0_、アメリカ.first_name as first 3_0_0_、アメリカ.ラスター.name as last 4_0_0_、アメリカ.birthday as birthday 0_0_from user 0_where user 0_.id=ですかHbernate:select user 0_.id as id 0_0_、アメリカ.version as version 0_0_、アメリカ.first_name as first 3_0_0_、アメリカ.ラスター.name as last 4_0_0_、アメリカ.birthday as birthday 0_0_from user 0_where user 0_.id=ですかHbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=Hbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=org.hibernatie.Store Object Station:Row was udated or deleted by another trannsaction(or unsaved-value mapping was incorection):[hibernantit.User ga 1]Excetion in in thread"marn.orgmbergeemberge.Extratetetetetection.Extratetetetetection.Extratection。s incorect):[hibernaetest.User〓1]udateUser法において、二つの事務を提出し、不一致が生じました。後に提出した事務は異常なロールバックされました。データベースに表の構造は:+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------name | ラスター.name birthday | +----+---------+-----------------+-----------+---------------------+ | 1| 1|new 1 first name me me lastName | 2009-02-08 14:32:43|+---------------------------------------------------------------------------------------------------------------は初めてデータを保存する場合、バージョン番号は0となります。更新後バージョン番号は1にアップグレードします。Hbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=この更新文は、hibernate内部はidとversionを参照していると説明しています。versionが一致しないと問題が発生します。versionタグを使う以外に、timestampタグも使用できます。タイムスタンプの種類は時間だけです。時間の前後を比較して、今回の事務の実行を決めます。ただし、極端な場合は、併発が高い場合には時間の差が小さく、区別が難しい時にはタイムスタンプが効かなくなります。だから一番確実なのはやはりバージョンでコントロールします。versionラベルのtype属性は、バージョンの属性タイプを指定できます。全体のタイプに加えて、タイムスタンプとして指定できます。これは、timestampタグを使うのと似ています。
public class Main {
public static void main(String[] args) {
User user = new User();
user.setBirthday(new Date());
saveUser(user);
updateUser(user.getId());
}
public static void saveUser(User user) {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Name name = new Name();
name.setFirstName("firstName");
name.setLastName("lastName");
user.setUserName(name);
session.save(user);
tx.commit();
session.close();
}
public static void updateUser(int id) {
Session s1 = HibernateUtil.getSession();
Transaction tx1 = s1.beginTransaction();
User user = (User)s1.get(User.class, id);
user.getUserName().setFirstName("new1 first name");//
Session s2 = HibernateUtil.getSession();
Transaction tx2 = s2.beginTransaction();
User user2 = (User)s2.get(User.class, id);
user2.getUserName().setFirstName("new2 first name");//
tx1.commit();
tx2.commit();
s1.close();
s2.close();
}
}
印刷出力のsql文は、ハイバーナ:insert into user(version、first uname、lastuuname、birthday)values(?、?、?)Hberra:select user 0_.id as id 0_0_、アメリカ.version as version 0_0_、アメリカ.first_name as first 3_0_0_、アメリカ.ラスター.name as last 4_0_0_、アメリカ.birthday as birthday 0_0_from user 0_where user 0_.id=ですかHbernate:select user 0_.id as id 0_0_、アメリカ.version as version 0_0_、アメリカ.first_name as first 3_0_0_、アメリカ.ラスター.name as last 4_0_0_、アメリカ.birthday as birthday 0_0_from user 0_where user 0_.id=ですかHbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=Hbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=org.hibernatie.Store Object Station:Row was udated or deleted by another trannsaction(or unsaved-value mapping was incorection):[hibernantit.User ga 1]Excetion in in thread"marn.orgmbergeemberge.Extratetetetetection.Extratetetetetection.Extratection。s incorect):[hibernaetest.User〓1]udateUser法において、二つの事務を提出し、不一致が生じました。後に提出した事務は異常なロールバックされました。データベースに表の構造は:+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------name | ラスター.name birthday | +----+---------+-----------------+-----------+---------------------+ | 1| 1|new 1 first name me me lastName | 2009-02-08 14:32:43|+---------------------------------------------------------------------------------------------------------------は初めてデータを保存する場合、バージョン番号は0となります。更新後バージョン番号は1にアップグレードします。Hbernate:udate user set version=?first_name=ラスター.name=bithday=where id=and version=この更新文は、hibernate内部はidとversionを参照していると説明しています。versionが一致しないと問題が発生します。versionタグを使う以外に、timestampタグも使用できます。タイムスタンプの種類は時間だけです。時間の前後を比較して、今回の事務の実行を決めます。ただし、極端な場合は、併発が高い場合には時間の差が小さく、区別が難しい時にはタイムスタンプが効かなくなります。だから一番確実なのはやはりバージョンでコントロールします。versionラベルのtype属性は、バージョンの属性タイプを指定できます。全体のタイプに加えて、タイムスタンプとして指定できます。これは、timestampタグを使うのと似ています。