2

値が赤の Car-entity 永続フィールドの色を使用した単純な質問:

00  @Transactional public class MyBean{...
01    public void test(){
02        Car c = s.find(Car.class,1);
03        c.setColor("blue");
04        test1(c);
05        System.out.println(c.getColor());   
06    }
07    @Transactional(readOnly=true)
08    public void test1(Car c){
09        c.setName("black");
10    }
11  }

Spring ORM TX-Transactional-Annotation 環境にあり、トランザクション セマンティクスとトランザクション スコープの永続コンテキストがあると仮定します。

コンソールには何が出力されますか?

  • 青い
4

2 に答える 2

4

同じインスタンスのメソッドを呼び出すときにトランザクション セマンティクスが有効であり、NESTED トランザクションが伝播されると仮定すると、永続化コンテキストのスコープによって異なります。

トランザクション スコープの永続化コンテキストを想定すると black、コンソールに出力されます。car インスタンスは、読み取り専用トランザクションの外部でフェッチされ、読み取り専用トランザクションにマージされていないため、デタッチされます。デタッチされたインスタンスでセッターを呼び出すことは安全です ( setColor("blue").

永続化コンテキストの拡張スコープを想定して: blackも表示されます。のjavadocから@Transactional

もしも

読み取り専用ヒントを解釈できないトランザクション マネージャーは、読み取り専用トランザクションを要求されたときに例外をスローしません。

また、JPA 2.0 仕様セクション 2.4.1.2 派生 ID のマッピングから:

リレーションシップに対応する埋め込まれた id 属性は、プロバイダによって「読み取り専用」として扱われます。つまり、アプリケーション側でそれらが更新されても、データベースには反映されません。

ただし、例外がスローされない場合、100% 確信はありません。color プロパティは埋め込み ID ではないため、動作が異なる場合があります。

トランザクションのセマンティクスがプロキシ経由で利用できる場合は、Adrian Shum の回答を参照してください。

于 2012-10-10T08:20:55.363 に答える
2

あなたは春のAOPの罠に陥ったと思います。

SpringでのトランザクションはAOPによって実現され、SpringでのAOPは、実際のターゲットの周りにプロキシを設定することで実現されます。

MyBeanの@Transactionalに注釈を付けました。他の誰かがのインスタンスを呼び出していると仮定MyBean.test()します。実際には、そのオブジェクトと直接「話し合っている」わけではありません。とまったく同じように見えるプロキシがありMyBeanますが、トランザクションを作成し、実際のを呼び出し、MyBean.test()その後、コミット/ロールバックします。

これは次のようなものです。

         test()                     test()
[Caller] ------->  [MyBean Proxy]  ------> [MyBean]

ただし、を呼び出す場合test1()、これはtest()実際にはthis.test1()を意味します。つまり、MyBeanインスタンスを直接呼び出すことを意味します。

          [MyBean Proxy]     [MyBean] <--
                                |       |  test1(c)
                                ---------

MyBean Proxy(トランザクショントリックを実行する責任がある)を通過しtest1()ないと、実際の呼び出しはトランザクションとは何の関係もありません。それは単なる方法です。

だからあなたは答えを知っています。

さらに、プロキシを介して呼び出すことができたとしても、話は変わりません。

          -> [MyBean Proxy]     [MyBean]
test1(c) |                         |
          -------------------------

これは、Car渡されたインスタンスがtest1()トランザクション(つまり、Hibernateセッション)で取得され、でtest()変更したものが何であれ、 (REQUIRED_NEW伝播を使用する場合)test1()個別に作成したHibernateセッションでは何も行わないためです。test1()渡されたオブジェクトの状態を変更するだけです。したがって、呼び出しtest1(c)は単純なメソッド呼び出しに他なりません。

于 2012-10-10T10:06:34.887 に答える