私はのためのサービスを実装しました、entity object
そしてそれは純粋を使用しますjpa
、私は使用spring
しました、それでimplとしてspring xml config
構成されました。運用にデータを使用しています。しかし、私たちのシステムでは、オブジェクトが何度もプル/更新されており、データとの競合が高くなっています。多くの場所のコードから、エンティティを取得するためのサービスBeanと呼び出しメソッドだけが多く、その後、エンティティが変更されます(これは私の理解では切り離されていますが、同じスレッドであるため、emオブジェクトは私の知識と同じである必要があります)そのため、エンティティがサービスに戻って更新されるまでしばらく時間がかかり、サービスのメソッドを呼び出してエンティティを保存します。メソッドはただ呼び出すだけですhibernate
jpa
spring
crud
entity
concurrency
classes
inject
getEntity
save()
Save()
merge()
Crud操作。@Transactional
注釈付きのトランザクションです。ここで問題が発生します。誰かがエンティティオブジェクトをプルし、それを変更しているときに他の誰かがそれをプルして変更して保存し直す可能性があるため、エンティティの読み取りがダーティであり、保存すると、すでに更新されたエンティティを上書きします。問題は、サービスの外部でエンティティを変更し、savebackを呼び出すことです。ここで、春のデータリポジトリクラスはDAOレイヤーです。
Optimistic lock
は1つの解決策ですが、何らかの理由で気に入らなかったため、機能しません。私は考えていpessimistic lock
ます。たとえば、ロックして更新するエンティティを取得し、それを別の場所に変更してコールバックすると(entity
更新に対してすでにロックされています!)、機能しますか?EntityManager
エンティティをプルするために使用したオブジェクトがまだそこにあるかどうかはわかりません。そこにある場合、更新されてロックが解除される前に、これらの「スマート」ロジックを渡すのに非常に長い時間がかかります。
シナリオの簡単なサンプルコードは次のとおりです。
class SomeEntity {
Long id;
String field1;
String field2;
String field3;
String field4;
String field5;
String field6;
String field7;
//getters and setters, column annotations
}
class SomeEntityServiceImple implemenet SomeEntityService{
@Transactional
save(SomeEntity se){
//call to spring data's merge() method
}
get(Long id){
//call to spring data's findOne()
}
}
//this class might be spring bean, might not be. If it is not I will get SomeEntityService bean from shared appContext
class SomeCrazyClass{
@Autowired
SomeEntityService service;
someMethod(){
SomeEntity e = service.get(1L);
//do tons of logic here, change entity object, call some another methods and again, takes 3 seond
service.save(e); //Probably detached and someone updated this object, probably overriding it.
}
}
}
ここでtons of logic
は、それをサービスレイヤー内に移動することはできません。これは非常に具体的であり、この種のさまざまなロジックは数百の場所にあります。
それで、回避して、少なくともこの状況に悲観的なロックを適用する方法はありますか?