StaleObjectStateException
私は1 週間以上に苦労しており、問題を再現する簡単なアプリをここに投稿することにしました。
が楽観的ロックorg.hibernate.StaleObjectStateException
の例外であることは理解しています。さらに、楽観的ロックは、各エンティティ クラスのバージョン フィールドの使用に依存しています。
ここで、上記の例外をどのように再現したかを説明します。サンプル アプリには、次のようなMember
エンティティ クラスがあります。
@RooJavaBean
@RooToString
@RooJpaEntity
public class Member {
@OneToOne(cascade=CascadeType.ALL)
private Address address;
//id, version fields as well as mutator/accessors are located in a separate Roo ITD/aspect
}
Address
エンティティクラスは次のとおりです。
@RooJavaBean
@RooToString
@RooJpaEntity
public class Address {
private String formattedAddress;
private double lng;
private double lat;
//id, version fields as well as mutator/accessors are located in a separate Roo ITD/aspect
}
新しい/管理されていない Address インスタンスと管理された Member インスタンスを使用してServiceImpl
、次のようにクラス内のメンバーのアドレスを更新しようとしています。
@Override
public void updateMemberAddress(Member member, Address address) {
long addressId = member.getAddress().getId();
address.setId(addressId);
updateAddress(address);
}
テストクラスは次のとおりです。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext*.xml")
@TransactionConfiguration(defaultRollback = false)
public class AddressIntegrationTest {
@Autowired
private Service service;
@Before
@Transactional
public void testInsertOneMember() {
Member member = new Member();
Address address = new Address();
address.setFormattedAddress("Eiffel Tower, Paris");
address.setLat(48.005);
address.setLng(3.288);
member.setAddress(address);
service.saveMember(member);
}
@Test
@Transactional
public void testUpdateAddress() {
Member member = service.findAllMembers().get(0);
Address address = new Address();
address.setFormattedAddress("Empire State Building, New York");
address.setLat(200.033);
address.setLng(36.665);
service.updateMemberAddress(member, address);
}
}
残念ながら、次のように恐ろしい StaleObjectStateException が発生します。
org.springframework.orm.jpa.JpaOptimisticLockingFailureException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.sose.domain.Address#1];
サンプル github アプリを使用して問題を再現するには、次のものが必要です。
- メイヴン
- ギット
- JDK6
- MySQL
次の手順に従って、問題を再現できます。
git clone git@github.com:balteo/StaleObjectStateException.git
- mysql で、sose というデータベース スキーマを作成します。
create database sose;
mvn test
- そして出来上がり:
BOOM
!
私の場合にこの例外が発生する理由と、この例外を取得せずに住所インスタンスを更新する方法を誰かに説明してもらえますか?