下面列出了怎么用org.hibernate.LockOptions的API类实例代码及写法,或者点击链接到github查看源代码。
@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);
}
});
}
private CompletionStage<List<Object>> performOrderedBatchLoad(
List<Serializable> idsInBatch,
LockOptions lockOptions,
OuterJoinLoadable persister,
SessionImplementor session) {
final int batchSize = idsInBatch.size();
final ReactiveDynamicBatchingEntityLoader batchingLoader = new ReactiveDynamicBatchingEntityLoader(
persister,
batchSize,
lockOptions,
session.getFactory(),
session.getLoadQueryInfluencers()
);
final Serializable[] idsInBatchArray = idsInBatch.toArray(new Serializable[0]);
QueryParameters qp = buildMultiLoadQueryParameters( persister, idsInBatchArray, lockOptions );
CompletionStage<List<Object>> result = batchingLoader.doEntityBatchFetch(session, qp, idsInBatchArray);
idsInBatch.clear();
return result;
}
/**
* Returns the set of pages that are linked from this page. Outlinks in a page might also point
* to non-existing pages. They are not included in the result set. <b>Warning:</b> Do not use
* this for getting the number of outlinks with {@link Page#getOutlinks()}.size(). This is too slow. Use
* {@link Page#getNumberOfOutlinks()} instead.
*
* @return The set of pages that are linked from this page.
*/
public Set<Page> getOutlinks()
{
Session session = wiki.__getHibernateSession();
session.beginTransaction();
// session.lock(hibernatePage, LockMode.NONE);
session.buildLockRequest(LockOptions.NONE).lock(hibernatePage);
// Have to copy links here since getPage later will close the session.
Set<Integer> tmpSet = new UnmodifiableArraySet<Integer>(hibernatePage.getOutLinks());
session.getTransaction().commit();
Set<Page> pages = new HashSet<Page>();
for (int pageID : tmpSet) {
try {
pages.add(wiki.getPage(pageID));
}
catch (WikiApiException e) {
// Silently ignore if a page could not be found.
// There may be outlinks pointing to non-existing pages.
}
}
return pages;
}
protected String generateLockString(int lockTimeout) {
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )
.addCondition( getLockable().getRootTableIdentifierColumnNames(), "=?" );
if ( getLockable().isVersioned() ) {
select.addCondition( getLockable().getVersionColumnName(), "=?" );
}
if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( getLockMode() + " lock " + getLockable().getEntityName() );
}
return select.toStatementString();
}
@Override
public <T> T get(final Class<T> entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@Override
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return session.get(entityClass, id, new LockOptions(lockMode));
}
else {
return session.get(entityClass, id);
}
}
});
}
@Override
public <T> T load(final Class<T> entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@Override
@SuppressWarnings("unchecked")
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return (T) session.load(entityClass, id, new LockOptions(lockMode));
}
else {
return (T) session.load(entityClass, id);
}
}
});
}
@Override
public CompletionStage<Object> load(Serializable id, Object optionalObject,
SharedSessionContractImplementor session,
LockOptions lockOptions, Boolean readOnly) {
final QueryParameters parameters = buildQueryParameters( id, optionalObject, lockOptions, readOnly );
String sql = getStaticLoadQuery().getSqlStatement();
return doReactiveQueryAndInitializeNonLazyCollections( sql, (SessionImplementor) session, parameters )
.thenApply( results -> extractEntityResult( results, id ) )
.handle( (list, err) -> {
CompletionStages.logSqlException( err,
() -> "could not load an entity: "
+ infoString( persister, id, persister.getIdentifierType(), getFactory() ),
sql
);
return CompletionStages.returnOrRethrow( err, list) ;
} );
}
@Override
public Object load(final String entityName, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<Object>() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return session.load(entityName, id, new LockOptions(lockMode));
}
else {
return session.load(entityName, id);
}
}
});
}
@Override
public <T> T load(final Class<T> entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@Override
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return session.load(entityClass, id, new LockOptions(lockMode));
}
else {
return session.load(entityClass, id);
}
}
});
}
@Test
public void testPessimisticWrite() {
LOGGER.info("Test lock contention");
doInJPA(entityManager -> {
List<Post> pendingPosts = entityManager.createQuery(
"select p " +
"from Post p " +
"where p.status = :status",
Post.class)
.setParameter("status", PostStatus.PENDING)
.setMaxResults(5)
//.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.unwrap(org.hibernate.Query.class)
.setLockOptions(new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeOut(LockOptions.SKIP_LOCKED))
.list();
assertEquals(5, pendingPosts.size());
});
}
@Override
public void delete(List<E> entityCollection) {
Session session = getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
for (E e: entityCollection) {
session.buildLockRequest(LockOptions.UPGRADE).lock(e);
session.delete(e);
session.flush();
session.evict(e);
}
if (!tx.wasCommitted()) tx.commit();
} catch (Exception ex) {
logger.error("Delete list failed", ex);
tx.rollback();
throw new HibernateException("Delete list failed");
}
}
/**
* @return The a set of categories that this page belongs to.
*/
public Set<Category> getCategories()
{
Session session = this.wiki.__getHibernateSession();
session.beginTransaction();
session.buildLockRequest(LockOptions.NONE).lock(hibernatePage);
Set<Integer> tmp = new UnmodifiableArraySet<Integer>(hibernatePage.getCategories());
session.getTransaction().commit();
Set<Category> categories = new HashSet<Category>();
for (int pageID : tmp) {
categories.add(wiki.getCategory(pageID));
}
return categories;
}
public LegacyBatchingEntityLoader(
OuterJoinLoadable persister,
int maxBatchSize,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) {
super( persister );
this.batchSizes = ArrayHelper.getBatchSizes( maxBatchSize );
this.loaders = new Loader[ batchSizes.length ];
for ( int i = 0; i < batchSizes.length; i++ ) {
this.loaders[i] = new EntityLoader( persister, batchSizes[i], lockOptions, factory, loadQueryInfluencers);
}
}
@Override
public <T> T load(final Class<T> entityClass, final Serializable id, @Nullable final LockMode lockMode)
throws DataAccessException {
return nonNull(executeWithNativeSession(session -> {
if (lockMode != null) {
return session.load(entityClass, id, new LockOptions(lockMode));
}
else {
return session.load(entityClass, id);
}
}));
}
@Override
public Object load(final String entityName, final Serializable id, @Nullable final LockMode lockMode)
throws DataAccessException {
return nonNull(executeWithNativeSession(session -> {
if (lockMode != null) {
return session.load(entityName, id, new LockOptions(lockMode));
}
else {
return session.load(entityName, id);
}
}));
}
@Override
public void delete(E e) {
try {
Session session = getCurrentSession();
session.buildLockRequest(LockOptions.UPGRADE).lock(e);
session.delete(e);
session.flush();
session.evict(e);
} catch (Exception ex) {
logger.error("Delete failed", ex);
throw new HibernateException("Delete failed");
}
}
public void lock(
Serializable id,
Object version,
Object object,
LockMode lockMode,
SharedSessionContractImplementor session) throws HibernateException {
getLocker( lockMode ).lock( id, version, object, LockOptions.WAIT_FOREVER, session );
}
@Test
public void testPessimisticReadBlocksUpdate() throws InterruptedException {
LOGGER.info("Test PESSIMISTIC_READ blocks UPDATE");
testPessimisticLocking(
(session, product) -> {
session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_READ)).lock(product);
LOGGER.info("PESSIMISTIC_READ acquired");
},
(session, product) -> {
product.setDescription("USB Flash Memory Stick");
session.flush();
LOGGER.info("Implicit lock acquired");
}
);
}
@Override
public void delete(final String entityName, final Object entity, @Nullable final LockMode lockMode)
throws DataAccessException {
executeWithNativeSession(session -> {
checkWriteOperationAllowed(session);
if (lockMode != null) {
session.buildLockRequest(new LockOptions(lockMode)).lock(entityName, entity);
}
session.delete(entityName, entity);
return null;
});
}
public void attachClean(T instance) {
try {
getSession().buildLockRequest(LockOptions.NONE).lock(instance);
logger.trace("attach successful");
} catch (RuntimeException re) {
logger.error("Failed attaching " + entityClass + " instance", re);
throw re;
}
}
protected Object load(
SharedSessionContractImplementor session,
Object id,
Object optionalObject,
Serializable optionalId,
LockOptions lockOptions) {
List list = loadEntity(
session,
id,
uniqueKeyType,
optionalObject,
entityName,
optionalId,
persister,
lockOptions
);
if ( list.size()==1 ) {
return list.get(0);
}
else if ( list.size()==0 ) {
return null;
}
else {
if ( getCollectionOwners()!=null ) {
return list.get(0);
}
else {
throw new HibernateException(
"More than one row with the given identifier was found: " +
id +
", for class: " +
persister.getEntityName()
);
}
}
}
@Override
protected UniqueEntityLoader buildBatchingLoader(
OuterJoinLoadable persister,
int batchSize,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers influencers) {
return new ReactivePaddedBatchingEntityLoader( persister, batchSize, lockOptions, factory, influencers );
}
public ReactiveDynamicBatchingEntityDelegator(
OuterJoinLoadable persister,
int maxBatchSize,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) {
super( persister );
this.maxBatchSize = maxBatchSize;
this.singleKeyLoader = new ReactiveEntityLoader( persister, 1, lockOptions, factory, loadQueryInfluencers );
this.dynamicLoader = new ReactiveDynamicBatchingEntityLoader( persister, maxBatchSize, lockOptions, factory, loadQueryInfluencers );
}
@Override
public CompletionStage<Object> load(
Serializable id,
Object optionalObject,
SharedSessionContractImplementor session,
LockOptions lockOptions) {
return load (id, optionalObject, session, lockOptions, null );
}
/**
* Builds a batch-fetch capable loader based on the given persister, lock-options, etc.
*
* @param persister The entity persister
* @param batchSize The maximum number of ids to batch-fetch at once
* @param lockOptions The lock options
* @param factory The SessionFactory
* @param influencers Any influencers that should affect the built query
*
* @return The loader.
*/
public UniqueEntityLoader buildLoader(
OuterJoinLoadable persister,
int batchSize,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers influencers) {
if ( batchSize <= 1 ) {
// no batching
return buildNonBatchingLoader( persister, lockOptions, factory, influencers );
}
return buildBatchingLoader( persister, batchSize, lockOptions, factory, influencers );
}
@Override
public String getReadLockString(int timeout) {
String readLockString = " for share";
if ( timeout == LockOptions.NO_WAIT ) {
return readLockString + " nowait ";
}
else if ( timeout == LockOptions.SKIP_LOCKED ) {
return readLockString + " skip locked ";
}
return readLockString;
}
@Override
public String getReadLockString(int timeout) {
if ( timeout == LockOptions.SKIP_LOCKED ) {
return " for share skip locked";
}
else {
return super.getReadLockString( timeout );
}
}
public ReactiveDynamicBatchingEntityLoader(
OuterJoinLoadable persister,
int maxBatchSize,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) {
this( persister, maxBatchSize, lockOptions.getLockMode(), factory, loadQueryInfluencers );
}
@Override
public void lock(final Object entity, final LockMode lockMode) throws DataAccessException {
executeWithNativeSession(new HibernateCallback<Object>() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
session.buildLockRequest(new LockOptions(lockMode)).lock(entity);
return null;
}
});
}
@Override
public CompletionStage<Object> load(Serializable id, Object optionalObject,
SharedSessionContractImplementor session,
Boolean readOnly) {
// this form is deprecated!
return load( id, optionalObject, session, LockOptions.NONE, readOnly );
}