私は、ユーザーがデータベースに相当な量のファイルをインポートする必要がある状況があります。標準インポートを実行してからレポートサマリーファイルを作成するか、インポートを「シミュレートする」(つまり、同じレポートサマリーを作成しますが、実際には何もインポートしない)ことができます。基本設定は以下の通りです。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()がうまくいかず、代わりに何をしなければならないのか理解してもらえますか?
多分代わりにトランザクションをロールバック? – spi
getEntityManager()はSpringのコンテキストからentityManagerを取得していますか? – rafaelim
なぜクリアが持続してはならないのか理由はありません。 L1キャッシュからオブジェクトを削除するだけです。 EntityManagerがそれについてまだ知らないとは限りません –