ヒベルナ学習の第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;}マッピングファイルの配置も相応の修正を行う必要があります。                          テストコード:
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タグを使うのと似ています。