use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.
the class LockTest method testContendedPessimisticWriteLockTimeout.
@Test
@RequiresDialect(OracleDialect.class)
@RequiresDialectFeature(DialectChecks.SupportsLockTimeouts.class)
public void testContendedPessimisticWriteLockTimeout() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final Lock lock = new Lock();
FutureTask<Boolean> bgTask = new FutureTask<>(() -> {
try {
// true (success) if LockTimeoutException occurred
AtomicBoolean timedOut = new AtomicBoolean();
doInJPA(this::entityManagerFactory, _entityManager -> {
log.info("testContendedPessimisticWriteLockTimeout: (BG) about to read write-locked entity");
// we should block on the following read
Lock lock2 = _entityManager.getReference(Lock.class, lock.getId());
// force entity to be read
lock2.getName();
log.info("testContendedPessimisticWriteLockTimeout: (BG) read write-locked entity");
Map<String, Object> props = new HashMap<String, Object>();
// timeout is in milliseconds
props.put(AvailableSettings.JPA_LOCK_TIMEOUT, 1000);
try {
_entityManager.lock(lock2, LockModeType.PESSIMISTIC_WRITE, props);
} catch (LockTimeoutException e) {
// success
log.info("testContendedPessimisticWriteLockTimeout: (BG) got expected timeout exception");
timedOut.set(true);
} catch (Throwable e) {
log.info("Expected LockTimeoutException but got unexpected exception", e);
}
});
return timedOut.get();
} finally {
// signal that we finished
latch.countDown();
}
});
Thread t = new Thread(bgTask);
t.setDaemon(true);
t.setName("Lock timeout Test (bg)");
try {
lock.setName("testContendedPessimisticWriteLockTimeout");
doInJPA(this::entityManagerFactory, em -> {
em.persist(lock);
});
doInJPA(this::entityManagerFactory, em -> {
Lock _lock = em.getReference(Lock.class, lock.getId());
em.lock(_lock, LockModeType.PESSIMISTIC_WRITE);
final Integer id = _lock.getId();
// force entity to be read
_lock.getName();
log.info("testContendedPessimisticWriteLockTimeout: got write lock");
try {
t.start();
// should return quickly on success
boolean latchSet = latch.await(20, TimeUnit.SECONDS);
assertTrue("background test thread finished (lock timeout is broken)", latchSet);
assertTrue("background test thread timed out on lock attempt", bgTask.get());
} catch (InterruptedException e) {
Thread.interrupted();
} catch (ExecutionException e) {
throw new AssertionError(e);
}
});
} finally {
awaitThenDelete("testContendedPessimisticWriteLockTimeout", t, lock.getId());
}
}
use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.
the class LockTest method testContendedPessimisticWriteLockNoWait.
@Test
@RequiresDialect({ OracleDialect.class, PostgreSQLDialect.class })
@RequiresDialectFeature(DialectChecks.SupportsLockTimeouts.class)
public void testContendedPessimisticWriteLockNoWait() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final Lock lock = new Lock();
FutureTask<Boolean> bgTask = new FutureTask<>(() -> {
try {
// true (success) if LockTimeoutException occurred
AtomicBoolean timedOut = new AtomicBoolean();
doInJPA(this::entityManagerFactory, _entityManager -> {
log.info("testContendedPessimisticWriteLockNoWait: (BG) about to read write-locked entity");
// we should block on the following read
Lock lock2 = _entityManager.getReference(Lock.class, lock.getId());
// force entity to be read
lock2.getName();
log.info("testContendedPessimisticWriteLockNoWait: (BG) read write-locked entity");
Map<String, Object> props = new HashMap<String, Object>();
// timeout of zero means no wait (for lock)
props.put(AvailableSettings.JPA_LOCK_TIMEOUT, 0);
try {
_entityManager.lock(lock2, LockModeType.PESSIMISTIC_WRITE, props);
} catch (LockTimeoutException e) {
// success
log.info("testContendedPessimisticWriteLockNoWait: (BG) got expected timeout exception");
timedOut.set(true);
} catch (Throwable e) {
log.info("Expected LockTimeoutException but got unexpected exception", e);
}
});
return timedOut.get();
} finally {
// signal that we finished
latch.countDown();
}
});
Thread t = new Thread(bgTask);
t.setDaemon(true);
t.setName("Lock timeout Test (bg)");
try {
lock.setName("testContendedPessimisticWriteLockNoWait");
doInJPA(this::entityManagerFactory, em -> {
em.persist(lock);
});
doInJPA(this::entityManagerFactory, em -> {
Lock _lock = em.getReference(Lock.class, lock.getId());
em.lock(_lock, LockModeType.PESSIMISTIC_WRITE);
final Integer id = _lock.getId();
// force entity to be read
_lock.getName();
log.info("testContendedPessimisticWriteLockNoWait: got write lock");
try {
t.start();
// should return quickly on success
boolean latchSet = latch.await(20, TimeUnit.SECONDS);
assertTrue("background test thread finished (lock timeout is broken)", latchSet);
assertTrue("background test thread timed out on lock attempt", bgTask.get());
} catch (InterruptedException e) {
Thread.interrupted();
} catch (ExecutionException e) {
throw new AssertionError(e);
}
});
} finally {
awaitThenDelete("testContendedPessimisticWriteLockNoWait", t, lock.getId());
}
}
use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.
the class LockExceptionTests method testLockTimeoutFind.
@Test
@TestForIssue(jiraKey = "HHH-8786")
public void testLockTimeoutFind() {
final Item item = new Item("find");
inTransaction(session -> session.persist(item));
try {
inTransaction(session -> {
session.find(Item.class, item.getId(), LockModeType.PESSIMISTIC_WRITE);
TransactionUtil2.inTransaction(sessionFactory(), secondSession -> {
try {
secondSession.find(Item.class, item.getId(), LockModeType.PESSIMISTIC_WRITE, Collections.singletonMap(AvailableSettings.JAKARTA_LOCK_TIMEOUT, LockOptions.NO_WAIT));
fail("Expecting a failure");
} catch (LockTimeoutException | PessimisticLockException expected) {
// expected outcome
}
});
});
} finally {
inTransaction(session -> session.createQuery("delete Item").executeUpdate());
}
}
use of jakarta.persistence.LockTimeoutException in project eclipselink by eclipse-ee4j.
the class QueryImpl method getSingleResult.
/**
* Execute a SELECT query that returns a single untyped result.
*
* @return the result
* @throws NoResultException if there is no result
* @throws NonUniqueResultException if more than one result
* @throws IllegalStateException if called for a Java Persistence query
* language UPDATE or DELETE statement
* @throws QueryTimeoutException if the query execution exceeds the query
* timeout value set and only the statement is rolled back
* @throws TransactionRequiredException if a lock mode other than NONE has
* been been set and there is no transaction or the persistence
* context has not been joined to the transaction
* @throws PessimisticLockException if pessimistic locking fails and the
* transaction is rolled back
* @throws LockTimeoutException if pessimistic locking fails and only the
* statement is rolled back
* @throws PersistenceException if the query execution exceeds the query
* timeout value set and the transaction is rolled back
*/
public Object getSingleResult() {
boolean rollbackOnException = true;
// bug51411440: need to throw IllegalStateException if query
// executed on closed em
this.entityManager.verifyOpenWithSetRollbackOnly();
try {
setAsSQLReadQuery();
propagateResultProperties();
// It could be Cursor or other Collection or Map type.
if (!(getDatabaseQueryInternal().isReadQuery())) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result"));
}
Object result = executeReadQuery();
if (result instanceof List) {
List results = (List) result;
if (results.isEmpty()) {
rollbackOnException = false;
throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
} else if (results.size() > 1) {
rollbackOnException = false;
throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null));
}
return results.get(0);
} else {
if (result == null) {
rollbackOnException = false;
throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
}
return result;
}
} catch (LockTimeoutException exception) {
throw exception;
} catch (PersistenceException exception) {
if (rollbackOnException) {
setRollbackOnly();
}
throw exception;
} catch (IllegalStateException exception) {
setRollbackOnly();
throw exception;
} catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
use of jakarta.persistence.LockTimeoutException in project eclipselink by eclipse-ee4j.
the class StoredProcedureQueryImpl method execute.
/**
* Returns true if the first result corresponds to a result set, and false
* if it is an update count or if there are no results other than through
* INOUT and OUT parameters, if any.
* @return true if first result corresponds to result set
* @throws QueryTimeoutException if the query execution exceeds the query
* timeout value set and only the statement is rolled back
* @throws PersistenceException if the query execution exceeds the query
* timeout value set and the transaction is rolled back
*/
@Override
public boolean execute() {
try {
entityManager.verifyOpen();
if (!getDatabaseQueryInternal().isResultSetMappingQuery()) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_execute"));
}
getResultSetMappingQuery().setIsExecuteCall(true);
executeCall = (DatabaseCall) executeReadQuery();
executeStatement = executeCall.getStatement();
// Add this query to the entity manager open queries list.
// The query will be closed in the following cases:
// Within a transaction:
// - on commit
// - on rollback
// Outside of a transaction:
// - em close
// Other safeguards, we will close the query if/when
// - we hit the end of the results.
// - this query is garbage collected (finalize method)
//
// Deferring closing the call avoids having to go through all the
// results now (and building all the result objects) and things
// remain on a as needed basis from the statement.
entityManager.addOpenQuery(this);
hasMoreResults = executeCall.getExecuteReturnValue();
// true and build the results from the output cursors.
if (!hasMoreResults && getCall().hasOutputCursors()) {
hasMoreResults = true;
outputCursorIndex = 0;
isOutputCursorResultSet = true;
}
return hasMoreResults;
} catch (LockTimeoutException exception) {
throw exception;
} catch (PersistenceException exception) {
setRollbackOnly();
throw exception;
} catch (IllegalStateException e) {
setRollbackOnly();
throw e;
} catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
Aggregations