2011-12-19 14 views
2

私はreadOnly Hibernateトランザクション内でオブジェクトを更新する必要があるこの非標準的な状況があります。物事は、私は多くの他のオブジェクトを読み込んで、そのトランザクション内でそれらを変更しますが、1つだけがロールバックされた状態で保存されるべきです。私が上で動作するデータベースは、PostgreSQL 8.4Spring + Hibernate + Postgresql readOnlyトランザクション、要求時保存

I`m私が正しくドキュメントを理解していないが、サービスメソッド作る:

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 

は保存そのため、明示的に新しいRWトランザクションを開くことになるはずです。

主なものは、これが動作していませんされています。その後

@Transactional(readOnly = true) 
public class PersonService { 

    @Resource(name="sessionFactory") 
    private SessionFactory sessionFactory; 

    public void add(Person person){ 

     person.setFirstName("changed its name"); 
     save(person); 
    } 

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
    public void save(Person person) { 

     Session session = sessionFactory.getCurrentSession(); 

     session.save(person); 
     session.flush(); 
    } 
} 

を私は '追加' メソッドを呼び出して、コントローラから

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update

を取得します。 'add'はreadOnlyモードであり、Personオブジェクトを 'save'メソッドに渡します。これは、新しいTransactionを開き、DBに保存する必要があります。 'add'メソッドの私のプロジェクトでは、私は他の多くの 'Person'オブジェクトがロードされていますが、これは保存すべきではありません。 私がreadOnlyメソッドを必要とする理由は、コード内でさらに多くのオブジェクトをロードすることです:)それらをロールバックすることは、私がしたい最後のことです。

このようにすることはできますか?

答えて

1

取引は、通常のポイントがでていることで、とにかく(あなたはちょうどあなたのコード例であるかもしれないインタフェースを実装していることを示していない?)

をサービス・インタフェースの実装を生成することによって、適用されていますその場合、単純にsave(...)を呼び出すのはラッパーを経由していないため、ターゲットオブジェクトのメソッドを実行しているだけです。サービスからの参照をそれ自体に注入する必要があります。そのため、自身を呼び出してラッピングを適用することができます。

public class PersonServiceImpl implements PersonService { 
    PersonService personService; 
    public void readOnlyMethod() { 
    // ... 
    personService.readWriteMethod(...); 
    } 
    public void readWriteMethod(...) { 
    } 
} 

とコールスタックは、次のようになります:それはある

PersonServiceImpl.readWriteMethod(...) 
TransactionAroundAdvice.advise(...) // starts/ends new read-write transaction 
$Proxy.readWriteMethod(...) // implementing PersonService 
PersonServiceImpl.readOnlyMethod(...) 
TransactionAroundAdvice.advise(...) // starts/ends read-only transaction 
$Proxy.readOnlyMethod(...) // implementing PersonService 
ClientCode.doSomethingNotReallyReadOnly(...) 

(あなたは私がRequiresNewの使用してきたところであるある種のエラーメッセージが表示され、ログ記録のような音を記述していますトランザクションマーキング(ただし、J2EEでは、私はそのポイントが運ぶと思う))

+0

+1うん、それはうまくいけない理由です。 @Resource(name = "personService")private PersonService personServiceを追加してpersonService.save(person)を呼び出すと、正常に動作し、データベースに保持されました。どうもありがとう! – Krystian

+0

ありがとうございました! :-) – Maciej

関連する問題