2017-07-13 28 views
0

私は、ユーザーがデータベースに相当な量のファイルをインポートする必要がある状況があります。標準インポートを実行してからレポートサマリーファイルを作成するか、インポートを「シミュレートする」(つまり、同じレポートサマリーを作成しますが、実際には何もインポートしない)ことができます。基本設定は以下の通りです。EntityManager.clear()はデータベースへのデータの書き込みを中止しません

public class Importer { 

    @Autowired 
    protected IConverter converter; 
    @Autowired 
    protected ISerializer serializer; 
    @Autowired 
    protected IReporter reporter; 


    public void import(InputStream stream) throws Exception { 
    CustomerData data = converter.convert(stream); 
    // ** database at this point has been updated! ** 
    if(getContext().isSerialize()) { 
     serializer.serialize(data); 
    } 
    if(getContext().isReport()) { 
     reporter.report(data, "report.xls"); 
    } 
    } 
} 

public class Converter implements IConverter throws Exception { 
    @Transactional 
    public CustomerData convert(InputStream stream) { 
    try { 
     CustomerData data = ... // read file and create/match with db entities 
     return data; 
    } finally { 
     if(!getContext().isSerialize()) { 
     // clear any changes made to objects made in the db 
     getEntityManager().clear(); 
     // ** database at this point is unaffected ** 
     } 
    } 
    } 
} 

ImporterはSpring 4.1で設定されたBeanクラスです。データベースはJPA 2.1/Hibernate 4.3.11/MySQL 5.5です。

CustomerDataオブジェクトは、データベースエンティティオブジェクトのツリーです(データベースのデータと一致する可能性があります(潜在的にインポートファイルのデータで更新されたプロパティを持つ可能性があります)。新しいエンティティであるものもあります。

isSerialize()およびisReport()によって、データベースが更新されるかどうかを制御できます。インポートをシミュレートするとき、isSerialize()= false、isReport()= true。

コードを実行すると、finallyブロックに入り、エンティティマネージャをクリアすると、データベースのデータはインポート前の状態になります。しかし、import()メソッドに戻ると、データベースはエンティティの変更で更新されました!

トランザクションインポート()メソッドが完了すると、データがコミットされるのは明らかですが、エンティティマネージャがクリアしても、変更が停止しないのはなぜですか?私が[Hibernate] AbstractEntityManagerImpl.flush()にブレークポイントを設定していることを確認するには、ここでは何も呼び出されません。

誰かが私がなぜclear()がうまくいかず、代わりに何をしなければならないのか理解してもらえますか?

+3

多分代わりにトランザクションをロールバック? – spi

+0

getEntityManager()はSpringのコンテキストからentityManagerを取得していますか? – rafaelim

+0

なぜクリアが持続してはならないのか理由はありません。 L1キャッシュからオブジェクトを削除するだけです。 EntityManagerがそれについてまだ知らないとは限りません –

答えて

0

私は正しい軌道に乗ってくれてありがとう、S.ピラー。同様の位置にいる人は、エンティティマネージャをクリアしても、トランザクションの最後にデータベースにコミットされているフラッシュされた変更を止めることはありません。clear()は最後のフラッシュから変更されたエンティティのみをクリアします。その周り

方法は、トランザクションをロールバックする必要があることをトランザクションマネージャに通知することである。

@Transactional 
    public CustomerData convert(InputStream stream) { 
    try { 
     CustomerData data = ... // read file and create/match with db entities 
     return data; 
    } finally { 
     if(!getContext().isSerialize()) { 
     // Ensure the current transaction is rolled back once the topmost @Transactional method completes. 
     TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 
     } 
    } 
    } 
関連する問題