下面列出了怎么用org.hibernate.StaleObjectStateException的API类实例代码及写法,或者点击链接到github查看源代码。
private Object[] getDatabaseSnapshot(SessionImplementor session, EntityPersister persister, Serializable id) {
if ( persister.isSelectBeforeUpdateRequired() ) {
Object[] snapshot = session.getPersistenceContext()
.getDatabaseSnapshot( id, persister );
if ( snapshot == null ) {
//do we even really need this? the update will fail anyway....
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatistics()
.optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), id );
}
return snapshot;
}
// TODO: optimize away this lookup for entities w/o unsaved-value="undefined"
final EntityKey entityKey = session.generateEntityKey( id, persister );
return session.getPersistenceContext().getCachedDatabaseSnapshot( entityKey );
}
private Object[] getDatabaseSnapshot(SessionImplementor session, EntityPersister persister, Serializable id) {
if ( persister.isSelectBeforeUpdateRequired() ) {
Object[] snapshot = session.getPersistenceContext()
.getDatabaseSnapshot(id, persister);
if (snapshot==null) {
//do we even really need this? the update will fail anyway....
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatisticsImplementor()
.optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), id );
}
else {
return snapshot;
}
}
else {
//TODO: optimize away this lookup for entities w/o unsaved-value="undefined"
EntityKey entityKey = new EntityKey( id, persister, session.getEntityMode() );
return session.getPersistenceContext()
.getCachedDatabaseSnapshot( entityKey );
}
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
post.setTitle("JPA");
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Alice: Optimistic locking failure", expected);
}
aliceLatch.countDown();
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
aliceLatch.await();
post.incrementLikes();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Bob: Optimistic locking failure", expected);
}
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
aliceLatch.await();
post.setViews(15);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Carol: Optimistic locking failure", expected);
}
}
private void testPessimisticLocking(LockRequestCallable primaryLockRequestCallable, LockRequestCallable secondaryLockRequestCallable) {
doInJPA(entityManager -> {
try {
Session session = entityManager.unwrap(Session.class);
Post post = entityManager.find(Post.class, 1L);
primaryLockRequestCallable.lock(session, post);
executeAsync(
() -> {
doInJPA(_entityManager -> {
Session _session = _entityManager.unwrap(Session.class);
Post _post = _entityManager.find(Post.class, 1L);
secondaryLockRequestCallable.lock(_session, _post);
});
},
endLatch::countDown
);
sleep(WAIT_MILLIS);
} catch (StaleObjectStateException e) {
LOGGER.info("Optimistic locking failure: ", e);
}
});
awaitOnLatch(endLatch);
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
entityManager.unwrap(Session.class).doWork(connection -> {
assertEquals(Connection.TRANSACTION_REPEATABLE_READ, connection.getTransactionIsolation());
});
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
post.setTitle("JPA");
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Alice: Optimistic locking failure", expected);
} catch (Exception unexpected) {
LOGGER.info("Alice: Optimistic locking failure due to MVCC", unexpected);
}
aliceLatch.countDown();
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
entityManager.unwrap(Session.class).doWork(connection -> {
assertEquals(Connection.TRANSACTION_REPEATABLE_READ, connection.getTransactionIsolation());
});
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
aliceLatch.await();
post.incrementLikes();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Bob: Optimistic locking failure", expected);
} catch (Exception unexpected) {
LOGGER.info("Bob: Optimistic locking failure due to MVCC", unexpected);
}
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
post.setTitle("JPA");
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Alice: Optimistic locking failure", expected);
}
aliceLatch.countDown();
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
aliceLatch.await();
post.incrementLikes();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Bob: Optimistic locking failure", expected);
}
}
@Override
public void run() {
try {
doInJPA(entityManager -> {
try {
Post post = entityManager.find(Post.class, 1L);
loadPostLatch.countDown();
loadPostLatch.await();
aliceLatch.await();
post.setViews(15);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Carol: Optimistic locking failure", expected);
}
}
@Test
public void testConcurrentPessimisticForceIncrementLockingFailFast() {
try {
doInJPA(entityManager -> {
Repository repository = entityManager.find(Repository.class, 1L);
executeSync(() -> {
doInJPA(_entityManager -> {
Repository _repository = _entityManager.find(Repository.class, 1L,
LockModeType.PESSIMISTIC_FORCE_INCREMENT);
Commit _commit = new Commit(_repository);
_commit.getChanges().add(new Change("Intro.md", "0a1,2..."));
_entityManager.persist(_commit);
});
});
entityManager.lock(repository, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
fail("Should have thrown StaleObjectStateException!");
});
} catch (OptimisticLockException expected) {
assertEquals(StaleObjectStateException.class, expected.getCause().getClass());
LOGGER.info("Failure: ", expected);
}
}
/**
*/
@Override
public void deleteBusinessGroup(BusinessGroup businessGroupTodelete) {
try {
// Delete the group object itself on the database
db.deleteObject(businessGroupTodelete);
} catch (final DBRuntimeException dbre) {
final Throwable th = dbre.getCause();
if ((th instanceof StaleObjectStateException) && (th.getMessage().startsWith("Row was updated or deleted by another transaction"))) {
// known issue OLAT-3654
log.info("Group was deleted by another user in the meantime. Known issue OLAT-3654");
throw new KnownIssueException("Group was deleted by another user in the meantime", 3654);
} else {
throw dbre;
}
}
}
/**
*/
@Override
public void deleteBusinessGroup(BusinessGroup businessGroupTodelete) {
try {
// Delete the group object itself on the database
db.deleteObject(businessGroupTodelete);
} catch (final DBRuntimeException dbre) {
final Throwable th = dbre.getCause();
if ((th instanceof StaleObjectStateException) && (th.getMessage().startsWith("Row was updated or deleted by another transaction"))) {
// known issue OLAT-3654
log.info("Group was deleted by another user in the meantime. Known issue OLAT-3654");
throw new KnownIssueException("Group was deleted by another user in the meantime", 3654, dbre);
} else {
throw dbre;
}
}
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
product.setQuantity(6L);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Alice: Optimistic locking failure", expected);
}
aliceLatch.countDown();
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
aliceLatch.await();
product.incrementLikes();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Bob: Optimistic locking failure", expected);
}
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
aliceLatch.await();
product.setDescription("Plasma HDTV");
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Vlad: Optimistic locking failure", expected);
}
}
private void testPessimisticLocking(ProductLockRequestCallable primaryLockRequestCallable, ProductLockRequestCallable secondaryLockRequestCallable) {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
primaryLockRequestCallable.lock(session, product);
executeAsync(
() -> {
doInTransaction(_session -> {
Product _product = (Product) _session.get(Product.class, 1L);
secondaryLockRequestCallable.lock(_session, _product);
});
},
endLatch::countDown
);
sleep(WAIT_MILLIS);
} catch (StaleObjectStateException e) {
LOGGER.info("Optimistic locking failure: ", e);
}
});
awaitOnLatch(endLatch);
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
product.setQuantity(6L);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Alice: Optimistic locking failure", expected);
}
aliceLatch.countDown();
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
aliceLatch.await();
product.incrementLikes();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Bob: Optimistic locking failure", expected);
}
}
@Override
public void run() {
try {
doInTransaction(session -> {
try {
Product product = (Product) session.get(Product.class, 1L);
loadProductsLatch.countDown();
loadProductsLatch.await();
aliceLatch.await();
product.setDescription("Plasma HDTV");
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
} catch (StaleObjectStateException expected) {
LOGGER.info("Vlad: Optimistic locking failure", expected);
}
}
@Test
public void testConcurrentPessimisticForceIncrementLockingFailFast() throws InterruptedException {
LOGGER.info("Test Concurrent PESSIMISTIC_FORCE_INCREMENT Lock Mode fail fast");
doInTransaction(session -> {
try {
Repository repository = (Repository) session.get(Repository.class, 1L);
executeSync(() -> {
doInTransaction(_session -> {
Repository _repository = (Repository) _session.get(Repository.class, 1L);
_session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_FORCE_INCREMENT)).lock(_repository);
Commit _commit = new Commit(_repository);
_commit.getChanges().add(new Change("index.html", "0a1,2..."));
_session.persist(_commit);
_session.flush();
});
});
session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_FORCE_INCREMENT)).lock(repository);
fail("Should have thrown StaleObjectStateException!");
} catch (StaleObjectStateException expected) {
LOGGER.info("Failure: ", expected);
}
});
}
@Test
public void whenUpdatingNonExistingObject_thenStaleStateException() {
thrown.expect(isA(OptimisticLockException.class));
thrown
.expectMessage("Row was updated or deleted by another transaction");
thrown.expectCause(isA(StaleObjectStateException.class));
Session session = null;
Transaction transaction = null;
try {
session = sessionFactory.openSession();
transaction = session.beginTransaction();
Product product1 = new Product();
product1.setId(15);
product1.setName("Product1");
session.update(product1);
transaction.commit();
} catch (Exception e) {
rollbackTransactionQuietly(transaction);
throw (e);
} finally {
closeSessionQuietly(session);
}
}
/**
* Check the version of the object in the <tt>ResultSet</tt> against
* the object version in the session cache, throwing an exception
* if the version numbers are different
*/
private void checkVersion(
final int i,
final Loadable persister,
final Serializable id,
final Object entity,
final ResultSet rs,
final SharedSessionContractImplementor session) throws HibernateException, SQLException {
Object version = session.getPersistenceContext().getEntry( entity ).getVersion();
if ( version != null ) { //null version means the object is in the process of being loaded somewhere else in the ResultSet
final VersionType versionType = persister.getVersionType();
final Object currentVersion = versionType.nullSafeGet(
rs,
getEntityAliases()[i].getSuffixedVersionAliases(),
session,
null
);
if ( !versionType.isEqual( version, currentVersion ) ) {
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatistics().optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), id );
}
}
}
private void checkVersion(
SharedSessionContractImplementor session,
ResultSet resultSet,
EntityPersister persister,
EntityAliases entityAliases,
EntityKey entityKey,
Object entityInstance) {
final Object version = session.getPersistenceContext().getEntry( entityInstance ).getVersion();
if ( version != null ) {
//null version means the object is in the process of being loaded somewhere else in the ResultSet
VersionType versionType = persister.getVersionType();
final Object currentVersion;
try {
currentVersion = versionType.nullSafeGet(
resultSet,
entityAliases.getSuffixedVersionAliases(),
session,
null
);
}
catch (SQLException e) {
throw session.getFactory().getServiceRegistry().getService( JdbcServices.class ).getSqlExceptionHelper().convert(
e,
"Could not read version value from result set"
);
}
if ( !versionType.isEqual( version, currentVersion ) ) {
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatistics().optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), entityKey.getIdentifier() );
}
}
}
@Override
public void lock(Serializable id, Object version, Object object, int timeout, SharedSessionContractImplementor session)
throws StaleObjectStateException, JDBCException {
if ( getLockMode().greaterThan( LockMode.READ ) ) {
LOG.hsqldbSupportsOnlyReadCommittedIsolation();
}
super.lock( id, version, object, timeout, session );
}
/**
* Check the version of the object in the <tt>ResultSet</tt> against
* the object version in the session cache, throwing an exception
* if the version numbers are different
*/
private void checkVersion(
final int i,
final Loadable persister,
final Serializable id,
final Object entity,
final ResultSet rs,
final SessionImplementor session)
throws HibernateException, SQLException {
Object version = session.getPersistenceContext().getEntry( entity ).getVersion();
if ( version != null ) { //null version means the object is in the process of being loaded somewhere else in the ResultSet
VersionType versionType = persister.getVersionType();
Object currentVersion = versionType.nullSafeGet(
rs,
getEntityAliases()[i].getSuffixedVersionAliases(),
session,
null
);
if ( !versionType.isEqual(version, currentVersion) ) {
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatisticsImplementor()
.optimisticFailure( persister.getEntityName() );
}
throw new StaleObjectStateException( persister.getEntityName(), id );
}
}
}
public void lock(Serializable id, Object version, Object object, SessionImplementor session)
throws StaleObjectStateException, JDBCException {
if ( getLockMode().greaterThan( LockMode.READ ) ) {
log.warn( "HSQLDB supports only READ_UNCOMMITTED isolation" );
}
super.lock( id, version, object, session );
}
public void updateGradebook(final Gradebook gradebook) throws StaleObjectModificationException {
final HibernateCallback hc = session -> {
// Get the gradebook and selected mapping from persistence
final Gradebook gradebookFromPersistence = (Gradebook)session.load(gradebook.getClass(), gradebook.getId());
final GradeMapping mappingFromPersistence = gradebookFromPersistence.getSelectedGradeMapping();
// If the mapping has changed, and there are explicitly entered
// course grade records, disallow this update.
if (!mappingFromPersistence.getId().equals(gradebook.getSelectedGradeMapping().getId())) {
if(isExplicitlyEnteredCourseGradeRecords(gradebook.getId())) {
throw new IllegalStateException("Selected grade mapping can not be changed, since explicit course grades exist.");
}
}
// Evict the persisted objects from the session and update the gradebook
// so the new grade mapping is used in the sort column update
//session.evict(mappingFromPersistence);
for (final Object element : gradebookFromPersistence.getGradeMappings()) {
session.evict(element);
}
session.evict(gradebookFromPersistence);
try {
session.update(gradebook);
session.flush();
} catch (final StaleObjectStateException e) {
throw new StaleObjectModificationException(e);
}
return null;
};
getHibernateTemplate().execute(hc);
}
public void updateGradebook(final Gradebook gradebook) throws StaleObjectModificationException {
final HibernateCallback hc = session -> {
// Get the gradebook and selected mapping from persistence
final Gradebook gradebookFromPersistence = (Gradebook)session.load(gradebook.getClass(), gradebook.getId());
final GradeMapping mappingFromPersistence = gradebookFromPersistence.getSelectedGradeMapping();
// If the mapping has changed, and there are explicitly entered
// course grade records, disallow this update.
if (!mappingFromPersistence.getId().equals(gradebook.getSelectedGradeMapping().getId())) {
if(isExplicitlyEnteredCourseGradeRecords(gradebook.getId())) {
throw new IllegalStateException("Selected grade mapping can not be changed, since explicit course grades exist.");
}
}
// Evict the persisted objects from the session and update the gradebook
// so the new grade mapping is used in the sort column update
//session.evict(mappingFromPersistence);
for (final Object element : gradebookFromPersistence.getGradeMappings()) {
session.evict(element);
}
session.evict(gradebookFromPersistence);
try {
session.update(gradebook);
session.flush();
} catch (final StaleObjectStateException e) {
throw new StaleObjectModificationException(e);
}
return null;
};
getHibernateTemplate().execute(hc);
}