HHH-4546 add JPA 2.0 locking. Still need more LockRequest support in AbstractEntityPersister.getAppropriateLoader(), may need to refactor.
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18016 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
a8e34f0066
commit
35ca4c3563
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains locking details (LockMode, Timeout and Scope).
|
||||||
|
*
|
||||||
|
* @author Scott Marlow
|
||||||
|
*/
|
||||||
|
public class LockRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public static final int NO_WAIT = 0;
|
||||||
|
public static final int WAIT_FOREVER = -1;
|
||||||
|
|
||||||
|
private LockMode lockMode = LockMode.NONE;
|
||||||
|
|
||||||
|
private int timeout = WAIT_FOREVER; // timeout in milliseconds, 0 = no wait, -1 = wait indefinitely
|
||||||
|
|
||||||
|
private boolean scope=false;// if true, cascade (pessimistic only) lock to collections and relationships
|
||||||
|
// owned by the entity.
|
||||||
|
|
||||||
|
public LockRequest() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRequest( LockMode lockMode, int timeout, boolean scope ) {
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the lock mode.
|
||||||
|
* @return the lock mode.
|
||||||
|
*/
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return lockMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the LockMode to be used. The default is LockMode.none.
|
||||||
|
*
|
||||||
|
* @param lockMode
|
||||||
|
* @return this LockRequest instance for operation chaining.
|
||||||
|
*/
|
||||||
|
public LockRequest setLockMode(LockMode lockMode) {
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timeout setting.
|
||||||
|
*
|
||||||
|
* @return timeout in milliseconds, -1 for indefinite wait and 0 for no wait.
|
||||||
|
*/
|
||||||
|
public int getTimeOut() {
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the pessimistic lock timeout (check if your dialect supports this option).
|
||||||
|
* The default pessimistic lock behavior is to wait forever for the lock.
|
||||||
|
*
|
||||||
|
* @param timeout is time in milliseconds to wait for lock. -1 means wait forever and 0 means no wait.
|
||||||
|
* @return this LockRequest instance for operation chaining.
|
||||||
|
*/
|
||||||
|
public LockRequest setTimeOut(int timeout) {
|
||||||
|
this.timeout = timeout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if locking is cascaded to owned collections and relationships.
|
||||||
|
* @return true if locking will be extended to owned collections and relationships.
|
||||||
|
*/
|
||||||
|
public boolean getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify if LockMode should be cascaded to owned collections and relationships.
|
||||||
|
* The association must be mapped with <tt>cascade="lock" for scope=true to work.
|
||||||
|
*
|
||||||
|
* @param scope
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public LockRequest setScope(boolean scope) {
|
||||||
|
this.scope = scope;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -270,9 +270,22 @@ public interface Session extends Serializable {
|
||||||
* @param lockMode the lock level
|
* @param lockMode the lock level
|
||||||
* @return the persistent instance or proxy
|
* @return the persistent instance or proxy
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException;
|
public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
|
* obtaining the specified lock mode, assuming the instance exists.
|
||||||
|
*
|
||||||
|
* @param theClass a persistent class
|
||||||
|
* @param id a valid identifier of an existing persistent instance of the class
|
||||||
|
* @param lockRequest contains the lock level
|
||||||
|
* @return the persistent instance or proxy
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public Object load(Class theClass, Serializable id, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance of the given entity class with the given identifier,
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
* obtaining the specified lock mode, assuming the instance exists.
|
* obtaining the specified lock mode, assuming the instance exists.
|
||||||
|
@ -282,9 +295,22 @@ public interface Session extends Serializable {
|
||||||
* @param lockMode the lock level
|
* @param lockMode the lock level
|
||||||
* @return the persistent instance or proxy
|
* @return the persistent instance or proxy
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
|
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
|
* obtaining the specified lock mode, assuming the instance exists.
|
||||||
|
*
|
||||||
|
* @param entityName a persistent class
|
||||||
|
* @param id a valid identifier of an existing persistent instance of the class
|
||||||
|
* @param lockRequest contains the lock level
|
||||||
|
* @return the persistent instance or proxy
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public Object load(String entityName, Serializable id, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance of the given entity class with the given identifier,
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
* assuming that the instance exists. This method might return a proxied instance that
|
* assuming that the instance exists. This method might return a proxied instance that
|
||||||
|
@ -500,29 +526,68 @@ public interface Session extends Serializable {
|
||||||
/**
|
/**
|
||||||
* Obtain the specified lock level upon the given object. This may be used to
|
* Obtain the specified lock level upon the given object. This may be used to
|
||||||
* perform a version check (<tt>LockMode.READ</tt>), to upgrade to a pessimistic
|
* perform a version check (<tt>LockMode.READ</tt>), to upgrade to a pessimistic
|
||||||
* lock (<tt>LockMode.UPGRADE</tt>), or to simply reassociate a transient instance
|
* lock (<tt>LockMode.PESSIMISTIC_WRITE</tt>), or to simply reassociate a transient instance
|
||||||
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
||||||
* instances if the association is mapped with <tt>cascade="lock"</tt>.
|
* instances if the association is mapped with <tt>cascade="lock"</tt>.
|
||||||
*
|
*
|
||||||
* @param object a persistent or transient instance
|
* @param object a persistent or transient instance
|
||||||
* @param lockMode the lock level
|
* @param lockMode the lock level
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public void lock(Object object, LockMode lockMode) throws HibernateException;
|
public void lock(Object object, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the specified lock level upon the given object. This may be used to
|
* Obtain the specified lock level upon the given object. This may be used to
|
||||||
* perform a version check (<tt>LockMode.READ</tt>), to upgrade to a pessimistic
|
* perform a version check (<tt>LockMode.OPTIMISTIC</tt>), to upgrade to a pessimistic
|
||||||
* lock (<tt>LockMode.UPGRADE</tt>), or to simply reassociate a transient instance
|
* lock (<tt>LockMode.PESSIMISTIC_WRITE</tt>), or to simply reassociate a transient instance
|
||||||
|
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
||||||
|
* instances if the association is mapped with <tt>cascade="lock" and lockRequest.getScope() == true</tt>.
|
||||||
|
*
|
||||||
|
* @param object a persistent or transient instance
|
||||||
|
* @param lockRequest contains the lock level
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public void lock(Object object, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the specified lock level upon the given object. This may be used to
|
||||||
|
* perform a version check (<tt>LockMode.OPTIMISTIC</tt>), to upgrade to a pessimistic
|
||||||
|
* lock (<tt>LockMode.PESSIMISTIC_WRITE</tt>), or to simply reassociate a transient instance
|
||||||
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
||||||
* instances if the association is mapped with <tt>cascade="lock"</tt>.
|
* instances if the association is mapped with <tt>cascade="lock"</tt>.
|
||||||
*
|
*
|
||||||
* @param object a persistent or transient instance
|
* @param object a persistent or transient instance
|
||||||
* @param lockMode the lock level
|
* @param lockMode the lock level
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException;
|
public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the specified lock level upon the given object. This may be used to
|
||||||
|
* perform a version check (<tt>LockMode.OPTIMISTIC</tt>), to upgrade to a pessimistic
|
||||||
|
* lock (<tt>LockMode.PESSIMISTIC_WRITE</tt>), or to simply reassociate a transient instance
|
||||||
|
* with a session (<tt>LockMode.NONE</tt>). This operation cascades to associated
|
||||||
|
* instances if the association is mapped with <tt>cascade="lock" and lockRequest.getScope() == true.</tt>.
|
||||||
|
*
|
||||||
|
* @param object a persistent or transient instance
|
||||||
|
* @param lockRequest contains the lock level
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public void lock(String entityName, Object object, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a lockRequest that specifies the LockMode, pessimistic lock timeout and lock scope.
|
||||||
|
* timeout and scope is ignored for optimistic locking.
|
||||||
|
*
|
||||||
|
* Use: LockRequest lr = session.buildLockRequest().setLockMode(LockMode.PESSIMISTIC_WRITE).setTimeOut(1000 * 60);
|
||||||
|
* session.lock(entity, lr);
|
||||||
|
*
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
LockRequest buildLockRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-read the state of the given instance from the underlying database. It is
|
* Re-read the state of the given instance from the underlying database. It is
|
||||||
* inadvisable to use this to implement long-running sessions that span many
|
* inadvisable to use this to implement long-running sessions that span many
|
||||||
|
@ -548,9 +613,22 @@ public interface Session extends Serializable {
|
||||||
* @param object a persistent or detached instance
|
* @param object a persistent or detached instance
|
||||||
* @param lockMode the lock mode to use
|
* @param lockMode the lock mode to use
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public void refresh(Object object, LockMode lockMode) throws HibernateException;
|
public void refresh(Object object, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-read the state of the given instance from the underlying database, with
|
||||||
|
* the given <tt>LockMode</tt>. It is inadvisable to use this to implement
|
||||||
|
* long-running sessions that span many business tasks. This method is, however,
|
||||||
|
* useful in certain special circumstances.
|
||||||
|
*
|
||||||
|
* @param object a persistent or detached instance
|
||||||
|
* @param lockRequest contains the lock mode to use
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public void refresh(Object object, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the current lock mode of the given object.
|
* Determine the current lock mode of the given object.
|
||||||
*
|
*
|
||||||
|
@ -688,9 +766,24 @@ public interface Session extends Serializable {
|
||||||
* @param lockMode the lock mode
|
* @param lockMode the lock mode
|
||||||
* @return a persistent instance or null
|
* @return a persistent instance or null
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException;
|
public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
|
* or null if there is no such persistent instance. (If the instance is already associated
|
||||||
|
* with the session, return that instance. This method never returns an uninitialized instance.)
|
||||||
|
* Obtain the specified lock mode if the instance exists.
|
||||||
|
*
|
||||||
|
* @param clazz a persistent class
|
||||||
|
* @param id an identifier
|
||||||
|
* @param lockRequest the lock mode
|
||||||
|
* @return a persistent instance or null
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public Object get(Class clazz, Serializable id, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the persistent instance of the given named entity with the given identifier,
|
* Return the persistent instance of the given named entity with the given identifier,
|
||||||
* or null if there is no such persistent instance. (If the instance is already associated
|
* or null if there is no such persistent instance. (If the instance is already associated
|
||||||
|
@ -714,9 +807,24 @@ public interface Session extends Serializable {
|
||||||
* @param lockMode the lock mode
|
* @param lockMode the lock mode
|
||||||
* @return a persistent instance or null
|
* @return a persistent instance or null
|
||||||
* @throws HibernateException
|
* @throws HibernateException
|
||||||
|
* @deprecated LockMode parameter should be replaced with a LockRequest
|
||||||
*/
|
*/
|
||||||
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
|
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the persistent instance of the given entity class with the given identifier,
|
||||||
|
* or null if there is no such persistent instance. (If the instance is already associated
|
||||||
|
* with the session, return that instance. This method never returns an uninitialized instance.)
|
||||||
|
* Obtain the specified lock mode if the instance exists.
|
||||||
|
*
|
||||||
|
* @param entityName the entity name
|
||||||
|
* @param id an identifier
|
||||||
|
* @param lockRequest contains the lock mode
|
||||||
|
* @return a persistent instance or null
|
||||||
|
* @throws HibernateException
|
||||||
|
*/
|
||||||
|
public Object get(String entityName, Serializable id, LockRequest lockRequest) throws HibernateException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the entity name for a persistent entity
|
* Return the entity name for a persistent entity
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.ReplicationMode;
|
import org.hibernate.ReplicationMode;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.collection.PersistentCollection;
|
import org.hibernate.collection.PersistentCollection;
|
||||||
|
@ -165,7 +166,17 @@ public abstract class CascadingAction {
|
||||||
if ( log.isTraceEnabled() ) {
|
if ( log.isTraceEnabled() ) {
|
||||||
log.trace( "cascading to lock: " + entityName );
|
log.trace( "cascading to lock: " + entityName );
|
||||||
}
|
}
|
||||||
session.lock( entityName, child, LockMode.NONE/*(LockMode) anything*/ );
|
LockMode lockMode = LockMode.NONE;
|
||||||
|
LockRequest lr = new LockRequest();
|
||||||
|
if ( anything instanceof LockRequest ) {
|
||||||
|
LockRequest lockRequest = (LockRequest)anything;
|
||||||
|
lr.setTimeOut(lockRequest.getTimeOut());
|
||||||
|
lr.setScope( lockRequest.getScope());
|
||||||
|
if ( lockRequest.getScope() == true ) // cascade specified lockMode
|
||||||
|
lockMode = lockRequest.getLockMode();
|
||||||
|
}
|
||||||
|
lr.setLockMode(lockMode);
|
||||||
|
session.lock( entityName, child, lr);
|
||||||
}
|
}
|
||||||
public Iterator getCascadableChildrenIterator(EventSource session, CollectionType collectionType, Object collection) {
|
public Iterator getCascadableChildrenIterator(EventSource session, CollectionType collectionType, Object collection) {
|
||||||
// lock doesn't cascade to uninitialized collections
|
// lock doesn't cascade to uninitialized collections
|
||||||
|
|
|
@ -27,6 +27,7 @@ package org.hibernate.event;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines an event class for the loading of an entity.
|
* Defines an event class for the loading of an entity.
|
||||||
|
@ -40,20 +41,24 @@ public class LoadEvent extends AbstractEvent {
|
||||||
private Serializable entityId;
|
private Serializable entityId;
|
||||||
private String entityClassName;
|
private String entityClassName;
|
||||||
private Object instanceToLoad;
|
private Object instanceToLoad;
|
||||||
private LockMode lockMode;
|
private LockRequest lockRequest;
|
||||||
private boolean isAssociationFetch;
|
private boolean isAssociationFetch;
|
||||||
private Object result;
|
private Object result;
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, Object instanceToLoad, EventSource source) {
|
public LoadEvent(Serializable entityId, Object instanceToLoad, EventSource source) {
|
||||||
this(entityId, null, instanceToLoad, null, false, source);
|
this(entityId, null, instanceToLoad, new LockRequest(), false, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, String entityClassName, LockMode lockMode, EventSource source) {
|
public LoadEvent(Serializable entityId, String entityClassName, LockMode lockMode, EventSource source) {
|
||||||
this(entityId, entityClassName, null, lockMode, false, source);
|
this(entityId, entityClassName, null, lockMode, false, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoadEvent(Serializable entityId, String entityClassName, LockRequest lockRequest, EventSource source) {
|
||||||
|
this(entityId, entityClassName, null, lockRequest, false, source);
|
||||||
|
}
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, String entityClassName, boolean isAssociationFetch, EventSource source) {
|
public LoadEvent(Serializable entityId, String entityClassName, boolean isAssociationFetch, EventSource source) {
|
||||||
this(entityId, entityClassName, null, null, isAssociationFetch, source);
|
this(entityId, entityClassName, null, new LockRequest(), isAssociationFetch, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssociationFetch() {
|
public boolean isAssociationFetch() {
|
||||||
|
@ -67,6 +72,16 @@ public class LoadEvent extends AbstractEvent {
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
boolean isAssociationFetch,
|
boolean isAssociationFetch,
|
||||||
EventSource source) {
|
EventSource source) {
|
||||||
|
this(entityId, entityClassName, instanceToLoad, new LockRequest().setLockMode(lockMode), isAssociationFetch, source );
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoadEvent(
|
||||||
|
Serializable entityId,
|
||||||
|
String entityClassName,
|
||||||
|
Object instanceToLoad,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
boolean isAssociationFetch,
|
||||||
|
EventSource source) {
|
||||||
|
|
||||||
super(source);
|
super(source);
|
||||||
|
|
||||||
|
@ -74,17 +89,17 @@ public class LoadEvent extends AbstractEvent {
|
||||||
throw new IllegalArgumentException("id to load is required for loading");
|
throw new IllegalArgumentException("id to load is required for loading");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lockMode == LockMode.WRITE ) {
|
if ( lockRequest.getLockMode() == LockMode.WRITE ) {
|
||||||
throw new IllegalArgumentException("Invalid lock mode for loading");
|
throw new IllegalArgumentException("Invalid lock mode for loading");
|
||||||
}
|
}
|
||||||
else if ( lockMode == null ) {
|
else if ( lockRequest.getLockMode() == null ) {
|
||||||
lockMode = DEFAULT_LOCK_MODE;
|
lockRequest.setLockMode(DEFAULT_LOCK_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
this.entityClassName = entityClassName;
|
this.entityClassName = entityClassName;
|
||||||
this.instanceToLoad = instanceToLoad;
|
this.instanceToLoad = instanceToLoad;
|
||||||
this.lockMode = lockMode;
|
this.lockRequest = lockRequest;
|
||||||
this.isAssociationFetch = isAssociationFetch;
|
this.isAssociationFetch = isAssociationFetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,12 +127,32 @@ public class LoadEvent extends AbstractEvent {
|
||||||
this.instanceToLoad = instanceToLoad;
|
this.instanceToLoad = instanceToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LockRequest getLockRequest() {
|
||||||
|
return lockRequest;
|
||||||
|
}
|
||||||
|
|
||||||
public LockMode getLockMode() {
|
public LockMode getLockMode() {
|
||||||
return lockMode;
|
return lockRequest.getLockMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLockMode(LockMode lockMode) {
|
public void setLockMode(LockMode lockMode) {
|
||||||
this.lockMode = lockMode;
|
this.lockRequest.setLockMode(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLockTimeout(int timeout) {
|
||||||
|
this.lockRequest.setTimeOut(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLockTimeout() {
|
||||||
|
return this.lockRequest.getTimeOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLockScope(boolean cascade) {
|
||||||
|
this.lockRequest.setScope(cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getLockScope() {
|
||||||
|
return this.lockRequest.getScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getResult() {
|
public Object getResult() {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
package org.hibernate.event;
|
package org.hibernate.event;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines an event class for the locking of an entity.
|
* Defines an event class for the locking of an entity.
|
||||||
|
@ -34,7 +35,7 @@ import org.hibernate.LockMode;
|
||||||
public class LockEvent extends AbstractEvent {
|
public class LockEvent extends AbstractEvent {
|
||||||
|
|
||||||
private Object object;
|
private Object object;
|
||||||
private LockMode lockMode;
|
private LockRequest lockRequest;
|
||||||
private String entityName;
|
private String entityName;
|
||||||
|
|
||||||
public LockEvent(String entityName, Object original, LockMode lockMode, EventSource source) {
|
public LockEvent(String entityName, Object original, LockMode lockMode, EventSource source) {
|
||||||
|
@ -42,10 +43,21 @@ public class LockEvent extends AbstractEvent {
|
||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LockEvent(String entityName, Object original, LockRequest lockRequest, EventSource source) {
|
||||||
|
this(original, lockRequest, source);
|
||||||
|
this.entityName = entityName;
|
||||||
|
}
|
||||||
|
|
||||||
public LockEvent(Object object, LockMode lockMode, EventSource source) {
|
public LockEvent(Object object, LockMode lockMode, EventSource source) {
|
||||||
super(source);
|
super(source);
|
||||||
this.object = object;
|
this.object = object;
|
||||||
this.lockMode = lockMode;
|
this.lockRequest = new LockRequest().setLockMode(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockEvent(Object object, LockRequest lockRequest, EventSource source) {
|
||||||
|
super(source);
|
||||||
|
this.object = object;
|
||||||
|
this.lockRequest = lockRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getObject() {
|
public Object getObject() {
|
||||||
|
@ -56,12 +68,32 @@ public class LockEvent extends AbstractEvent {
|
||||||
this.object = object;
|
this.object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LockRequest getLockRequest() {
|
||||||
|
return lockRequest;
|
||||||
|
}
|
||||||
|
|
||||||
public LockMode getLockMode() {
|
public LockMode getLockMode() {
|
||||||
return lockMode;
|
return lockRequest.getLockMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLockMode(LockMode lockMode) {
|
public void setLockMode(LockMode lockMode) {
|
||||||
this.lockMode = lockMode;
|
this.lockRequest.setLockMode(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLockTimeout(int timeout) {
|
||||||
|
this.lockRequest.setTimeOut(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLockTimeout() {
|
||||||
|
return this.lockRequest.getTimeOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLockScope(boolean cascade) {
|
||||||
|
this.lockRequest.setScope(cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getLockScope() {
|
||||||
|
return this.lockRequest.getScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEntityName() {
|
public String getEntityName() {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
package org.hibernate.event;
|
package org.hibernate.event;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines an event class for the refreshing of an object.
|
* Defines an event class for the refreshing of an object.
|
||||||
|
@ -34,7 +35,7 @@ import org.hibernate.LockMode;
|
||||||
public class RefreshEvent extends AbstractEvent {
|
public class RefreshEvent extends AbstractEvent {
|
||||||
|
|
||||||
private Object object;
|
private Object object;
|
||||||
private LockMode lockMode = LockMode.READ;
|
private LockRequest lockRequest = new LockRequest().setLockMode(LockMode.READ);
|
||||||
|
|
||||||
public RefreshEvent(Object object, EventSource source) {
|
public RefreshEvent(Object object, EventSource source) {
|
||||||
super(source);
|
super(source);
|
||||||
|
@ -49,14 +50,34 @@ public class RefreshEvent extends AbstractEvent {
|
||||||
if (lockMode == null) {
|
if (lockMode == null) {
|
||||||
throw new IllegalArgumentException("Attempt to generate refresh event with null lock mode");
|
throw new IllegalArgumentException("Attempt to generate refresh event with null lock mode");
|
||||||
}
|
}
|
||||||
this.lockMode = lockMode;
|
this.lockRequest.setLockMode(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefreshEvent(Object object, LockRequest lockRequest, EventSource source) {
|
||||||
|
this(object, source);
|
||||||
|
if (lockRequest == null) {
|
||||||
|
throw new IllegalArgumentException("Attempt to generate refresh event with null lock request");
|
||||||
|
}
|
||||||
|
this.lockRequest = lockRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getObject() {
|
public Object getObject() {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LockRequest getLockRequest() {
|
||||||
|
return lockRequest;
|
||||||
|
}
|
||||||
|
|
||||||
public LockMode getLockMode() {
|
public LockMode getLockMode() {
|
||||||
return lockMode;
|
return lockRequest.getLockMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLockTimeout() {
|
||||||
|
return this.lockRequest.getTimeOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getLockScope() {
|
||||||
|
return this.lockRequest.getScope();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.ObjectDeletedException;
|
import org.hibernate.ObjectDeletedException;
|
||||||
import org.hibernate.OptimisticLockException;
|
import org.hibernate.OptimisticLockException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.event.EventSource;
|
import org.hibernate.event.EventSource;
|
||||||
import org.hibernate.action.EntityIncrementVersionProcess;
|
import org.hibernate.action.EntityIncrementVersionProcess;
|
||||||
import org.hibernate.action.EntityVerifyVersionProcess;
|
import org.hibernate.action.EntityVerifyVersionProcess;
|
||||||
|
@ -55,11 +56,12 @@ public class AbstractLockUpgradeEventListener extends AbstractReassociateEventLi
|
||||||
*
|
*
|
||||||
* @param object The entity for which to upgrade the lock.
|
* @param object The entity for which to upgrade the lock.
|
||||||
* @param entry The entity's EntityEntry instance.
|
* @param entry The entity's EntityEntry instance.
|
||||||
* @param requestedLockMode The lock mode being requested for locking.
|
* @param lockRequest contains the requested lock mode.
|
||||||
* @param source The session which is the source of the event being processed.
|
* @param source The session which is the source of the event being processed.
|
||||||
*/
|
*/
|
||||||
protected void upgradeLock(Object object, EntityEntry entry, LockMode requestedLockMode, EventSource source) {
|
protected void upgradeLock(Object object, EntityEntry entry, LockRequest lockRequest, EventSource source) {
|
||||||
|
|
||||||
|
LockMode requestedLockMode = lockRequest.getLockMode();
|
||||||
if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) {
|
if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) {
|
||||||
// The user requested a "greater" (i.e. more restrictive) form of
|
// The user requested a "greater" (i.e. more restrictive) form of
|
||||||
// pessimistic lock
|
// pessimistic lock
|
||||||
|
|
|
@ -485,7 +485,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
return INCONSISTENT_RTN_CLASS_MARKER;
|
return INCONSISTENT_RTN_CLASS_MARKER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
upgradeLock( old, oldEntry, event.getLockMode(), event.getSession() );
|
upgradeLock( old, oldEntry, event.getLockRequest(), event.getSession() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
|
|
|
@ -80,11 +80,10 @@ public class DefaultLockEventListener extends AbstractLockUpgradeEventListener i
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = reassociate(event, entity, id, persister);
|
entry = reassociate(event, entity, id, persister);
|
||||||
// TODO: make cascadeOnLock optional based on SCOPE
|
|
||||||
cascadeOnLock(event, persister, entity);
|
cascadeOnLock(event, persister, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeLock( entity, entry, event.getLockMode(), event.getSession() );
|
upgradeLock( entity, entry, event.getLockRequest(), event.getSession() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cascadeOnLock(LockEvent event, EntityPersister persister, Object entity) {
|
private void cascadeOnLock(LockEvent event, EntityPersister persister, Object entity) {
|
||||||
|
@ -92,7 +91,7 @@ public class DefaultLockEventListener extends AbstractLockUpgradeEventListener i
|
||||||
source.getPersistenceContext().incrementCascadeLevel();
|
source.getPersistenceContext().incrementCascadeLevel();
|
||||||
try {
|
try {
|
||||||
new Cascade(CascadingAction.LOCK, Cascade.AFTER_LOCK, source)
|
new Cascade(CascadingAction.LOCK, Cascade.AFTER_LOCK, source)
|
||||||
.cascade( persister, entity, event.getLockMode() );
|
.cascade( persister, entity, event.getLockRequest() );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
source.getPersistenceContext().decrementCascadeLevel();
|
source.getPersistenceContext().decrementCascadeLevel();
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
|
|
||||||
String previousFetchProfile = source.getFetchProfile();
|
String previousFetchProfile = source.getFetchProfile();
|
||||||
source.setFetchProfile("refresh");
|
source.setFetchProfile("refresh");
|
||||||
Object result = persister.load( id, object, event.getLockMode(), source );
|
Object result = persister.load( id, object, event.getLockRequest(), source );
|
||||||
source.setFetchProfile(previousFetchProfile);
|
source.setFetchProfile(previousFetchProfile);
|
||||||
|
|
||||||
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
|
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.hibernate.TransientObjectException;
|
||||||
import org.hibernate.UnresolvableObjectException;
|
import org.hibernate.UnresolvableObjectException;
|
||||||
import org.hibernate.UnknownProfileException;
|
import org.hibernate.UnknownProfileException;
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.collection.PersistentCollection;
|
import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.engine.ActionQueue;
|
import org.hibernate.engine.ActionQueue;
|
||||||
import org.hibernate.engine.CollectionEntry;
|
import org.hibernate.engine.CollectionEntry;
|
||||||
|
@ -134,7 +135,6 @@ import org.hibernate.type.SerializationException;
|
||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
import org.hibernate.util.CollectionHelper;
|
import org.hibernate.util.CollectionHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
import org.hibernate.util.SerializationHelper;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -742,10 +742,23 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
fireLock( new LockEvent(entityName, object, lockMode, this) );
|
fireLock( new LockEvent(entityName, object, lockMode, this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void lock(String entityName, Object object, LockRequest lockRequest) throws HibernateException {
|
||||||
|
fireLock( new LockEvent(entityName, object, lockRequest, this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRequest buildLockRequest() {
|
||||||
|
return new LockRequest();
|
||||||
|
}
|
||||||
|
|
||||||
public void lock(Object object, LockMode lockMode) throws HibernateException {
|
public void lock(Object object, LockMode lockMode) throws HibernateException {
|
||||||
fireLock( new LockEvent(object, lockMode, this) );
|
fireLock( new LockEvent(object, lockMode, this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void lock(Object object, LockRequest lockRequest) throws HibernateException {
|
||||||
|
fireLock( new LockEvent(object, lockRequest, this) );
|
||||||
|
}
|
||||||
|
|
||||||
private void fireLock(LockEvent lockEvent) {
|
private void fireLock(LockEvent lockEvent) {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1024,22 +1037,42 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return load( entityClass.getName(), id, lockMode );
|
return load( entityClass.getName(), id, lockMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object load(Class entityClass, Serializable id, LockRequest lockRequest) throws HibernateException {
|
||||||
|
return load( entityClass.getName(), id, lockRequest );
|
||||||
|
}
|
||||||
|
|
||||||
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
|
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
|
||||||
LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
|
LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
|
||||||
fireLoad( event, LoadEventListener.LOAD );
|
fireLoad( event, LoadEventListener.LOAD );
|
||||||
return event.getResult();
|
return event.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object load(String entityName, Serializable id, LockRequest lockRequest) throws HibernateException {
|
||||||
|
LoadEvent event = new LoadEvent(id, entityName, lockRequest, this);
|
||||||
|
fireLoad( event, LoadEventListener.LOAD );
|
||||||
|
return event.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
public Object get(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
|
public Object get(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
|
||||||
return get( entityClass.getName(), id, lockMode );
|
return get( entityClass.getName(), id, lockMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object get(Class entityClass, Serializable id, LockRequest lockRequest) throws HibernateException {
|
||||||
|
return get( entityClass.getName(), id, lockRequest );
|
||||||
|
}
|
||||||
|
|
||||||
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
|
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
|
||||||
LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
|
LoadEvent event = new LoadEvent(id, entityName, lockMode, this);
|
||||||
fireLoad(event, LoadEventListener.GET);
|
fireLoad(event, LoadEventListener.GET);
|
||||||
return event.getResult();
|
return event.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object get(String entityName, Serializable id, LockRequest lockRequest) throws HibernateException {
|
||||||
|
LoadEvent event = new LoadEvent(id, entityName, lockRequest, this);
|
||||||
|
fireLoad(event, LoadEventListener.GET);
|
||||||
|
return event.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
private void fireLoad(LoadEvent event, LoadType loadType) {
|
private void fireLoad(LoadEvent event, LoadType loadType) {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1060,6 +1093,10 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
fireRefresh( new RefreshEvent(object, lockMode, this) );
|
fireRefresh( new RefreshEvent(object, lockMode, this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refresh(Object object, LockRequest lockRequest) throws HibernateException {
|
||||||
|
fireRefresh( new RefreshEvent(object, lockRequest, this) );
|
||||||
|
}
|
||||||
|
|
||||||
public void refresh(Object object, Map refreshedAlready) throws HibernateException {
|
public void refresh(Object object, Map refreshedAlready) throws HibernateException {
|
||||||
fireRefresh( refreshedAlready, new RefreshEvent(object, this) );
|
fireRefresh( refreshedAlready, new RefreshEvent(object, this) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Iterator;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
|
@ -94,6 +95,29 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
||||||
initStatementString( whereString, orderByString, lockMode);
|
initStatementString( whereString, orderByString, lockMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final void initAll(
|
||||||
|
final String whereString,
|
||||||
|
final String orderByString,
|
||||||
|
final LockRequest lockRequest) throws MappingException {
|
||||||
|
walkEntityTree( persister, getAlias() );
|
||||||
|
List allAssociations = new ArrayList();
|
||||||
|
allAssociations.addAll(associations);
|
||||||
|
allAssociations.add(
|
||||||
|
new OuterJoinableAssociation(
|
||||||
|
persister.getEntityType(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
alias,
|
||||||
|
JoinFragment.LEFT_OUTER_JOIN,
|
||||||
|
null,
|
||||||
|
getFactory(),
|
||||||
|
CollectionHelper.EMPTY_MAP
|
||||||
|
)
|
||||||
|
);
|
||||||
|
initPersisters(allAssociations, lockRequest.getLockMode());
|
||||||
|
initStatementString( whereString, orderByString, lockRequest.getLockMode());
|
||||||
|
}
|
||||||
|
|
||||||
protected final void initProjection(
|
protected final void initProjection(
|
||||||
final String projectionString,
|
final String projectionString,
|
||||||
final String whereString,
|
final String whereString,
|
||||||
|
|
|
@ -28,8 +28,6 @@ import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Set;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
|
@ -128,4 +129,24 @@ public class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniqueEntityLoader createBatchingEntityLoader(
|
||||||
|
final OuterJoinLoadable persister,
|
||||||
|
final int maxBatchSize,
|
||||||
|
final LockRequest lockRequest,
|
||||||
|
final SessionFactoryImplementor factory,
|
||||||
|
final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
|
||||||
|
if ( maxBatchSize>1 ) {
|
||||||
|
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
||||||
|
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
||||||
|
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
|
||||||
|
loadersToCreate[i] = new EntityLoader(persister, batchSizesToCreate[i], lockRequest, factory, loadQueryInfluencers);
|
||||||
|
}
|
||||||
|
return new BatchingEntityLoader(persister, batchSizesToCreate, loadersToCreate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new EntityLoader(persister, lockRequest, factory, loadQueryInfluencers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Iterator;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
|
@ -47,7 +48,7 @@ import org.hibernate.type.AssociationType;
|
||||||
*/
|
*/
|
||||||
public class EntityJoinWalker extends AbstractEntityJoinWalker {
|
public class EntityJoinWalker extends AbstractEntityJoinWalker {
|
||||||
|
|
||||||
private final LockMode lockMode;
|
private final LockRequest lockRequest = new LockRequest();
|
||||||
|
|
||||||
public EntityJoinWalker(
|
public EntityJoinWalker(
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
|
@ -58,13 +59,33 @@ public class EntityJoinWalker extends AbstractEntityJoinWalker {
|
||||||
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
super( persister, factory, loadQueryInfluencers );
|
super( persister, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
this.lockMode = lockMode;
|
this.lockRequest.setLockMode(lockMode);
|
||||||
|
|
||||||
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
|
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
|
||||||
//include the discriminator and class-level where, but not filters
|
//include the discriminator and class-level where, but not filters
|
||||||
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
|
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
|
||||||
|
|
||||||
initAll( whereCondition.toString(), "", lockMode );
|
initAll( whereCondition.toString(), "", lockRequest );
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityJoinWalker(
|
||||||
|
OuterJoinLoadable persister,
|
||||||
|
String[] uniqueKey,
|
||||||
|
int batchSize,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
super( persister, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
|
this.lockRequest.setLockMode(lockRequest.getLockMode());
|
||||||
|
this.lockRequest.setTimeOut(lockRequest.getTimeOut());
|
||||||
|
this.lockRequest.setScope(lockRequest.getScope());
|
||||||
|
|
||||||
|
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
|
||||||
|
//include the discriminator and class-level where, but not filters
|
||||||
|
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
|
||||||
|
|
||||||
|
initAll( whereCondition.toString(), "", lockRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getJoinType(
|
protected int getJoinType(
|
||||||
|
@ -81,7 +102,7 @@ public class EntityJoinWalker extends AbstractEntityJoinWalker {
|
||||||
// NOTE : we override this form here specifically to account for
|
// NOTE : we override this form here specifically to account for
|
||||||
// fetch profiles.
|
// fetch profiles.
|
||||||
// TODO : how to best handle criteria queries?
|
// TODO : how to best handle criteria queries?
|
||||||
if ( lockMode.greaterThan( LockMode.READ ) ) {
|
if ( lockRequest.getLockMode().greaterThan( LockMode.READ ) ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ( isTooDeep( currentDepth )
|
if ( isTooDeep( currentDepth )
|
||||||
|
|
|
@ -24,12 +24,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.entity;
|
package org.hibernate.loader.entity;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
|
@ -57,6 +55,14 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
this( persister, 1, lockMode, factory, loadQueryInfluencers );
|
this( persister, 1, lockMode, factory, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityLoader(
|
||||||
|
OuterJoinLoadable persister,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
this( persister, 1, lockRequest, factory, loadQueryInfluencers );
|
||||||
|
}
|
||||||
|
|
||||||
public EntityLoader(
|
public EntityLoader(
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
int batchSize,
|
int batchSize,
|
||||||
|
@ -74,6 +80,23 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityLoader(
|
||||||
|
OuterJoinLoadable persister,
|
||||||
|
int batchSize,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
this(
|
||||||
|
persister,
|
||||||
|
persister.getIdentifierColumnNames(),
|
||||||
|
persister.getIdentifierType(),
|
||||||
|
batchSize,
|
||||||
|
lockRequest,
|
||||||
|
factory,
|
||||||
|
loadQueryInfluencers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public EntityLoader(
|
public EntityLoader(
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
String[] uniqueKey,
|
String[] uniqueKey,
|
||||||
|
@ -102,6 +125,34 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityLoader(
|
||||||
|
OuterJoinLoadable persister,
|
||||||
|
String[] uniqueKey,
|
||||||
|
Type uniqueKeyType,
|
||||||
|
int batchSize,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
super( persister, uniqueKeyType, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
|
JoinWalker walker = new EntityJoinWalker(
|
||||||
|
persister,
|
||||||
|
uniqueKey,
|
||||||
|
batchSize,
|
||||||
|
lockRequest,
|
||||||
|
factory,
|
||||||
|
loadQueryInfluencers
|
||||||
|
);
|
||||||
|
initFromWalker( walker );
|
||||||
|
|
||||||
|
postInstantiate();
|
||||||
|
|
||||||
|
batchLoader = batchSize > 1;
|
||||||
|
|
||||||
|
log.debug( "Static select for entity " + entityName + ": " + getSQLString() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public Object loadByUniqueKey(
|
public Object loadByUniqueKey(
|
||||||
SessionImplementor session,
|
SessionImplementor session,
|
||||||
Object key) throws HibernateException {
|
Object key) throws HibernateException {
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.StaleObjectStateException;
|
import org.hibernate.StaleObjectStateException;
|
||||||
import org.hibernate.StaleStateException;
|
import org.hibernate.StaleStateException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.cache.CacheKey;
|
import org.hibernate.cache.CacheKey;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
import org.hibernate.cache.entry.CacheEntry;
|
import org.hibernate.cache.entry.CacheEntry;
|
||||||
|
@ -1412,7 +1413,16 @@ public abstract class AbstractEntityPersister
|
||||||
Object object,
|
Object object,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionImplementor session) throws HibernateException {
|
SessionImplementor session) throws HibernateException {
|
||||||
getLocker( lockMode ).lock( id, version, object, -1, session );
|
getLocker( lockMode ).lock( id, version, object, LockRequest.WAIT_FOREVER, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lock(
|
||||||
|
Serializable id,
|
||||||
|
Object version,
|
||||||
|
Object object,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionImplementor session) throws HibernateException {
|
||||||
|
getLocker( lockRequest.getLockMode() ).lock( id, version, object, lockRequest.getTimeOut(), session );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRootTableName() {
|
public String getRootTableName() {
|
||||||
|
@ -1871,6 +1881,19 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected UniqueEntityLoader createEntityLoader(
|
||||||
|
LockRequest lockRequest,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
|
//TODO: disable batch loading if lockMode > READ?
|
||||||
|
return BatchingEntityLoader.createBatchingEntityLoader(
|
||||||
|
this,
|
||||||
|
batchSize,
|
||||||
|
lockRequest,
|
||||||
|
getFactory(),
|
||||||
|
loadQueryInfluencers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws MappingException {
|
protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws MappingException {
|
||||||
return createEntityLoader( lockMode, LoadQueryInfluencers.NONE );
|
return createEntityLoader( lockMode, LoadQueryInfluencers.NONE );
|
||||||
}
|
}
|
||||||
|
@ -3185,7 +3208,25 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UniqueEntityLoader loader = getAppropriateLoader( lockMode, session );
|
final UniqueEntityLoader loader = getAppropriateLoader( new LockRequest().setLockMode(lockMode), session );
|
||||||
|
return loader.load( id, optionalObject, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an instance using either the <tt>forUpdateLoader</tt> or the outer joining <tt>loader</tt>,
|
||||||
|
* depending upon the value of the <tt>lock</tt> parameter
|
||||||
|
*/
|
||||||
|
public Object load(Serializable id, Object optionalObject, LockRequest lockRequest, SessionImplementor session)
|
||||||
|
throws HibernateException {
|
||||||
|
|
||||||
|
if ( log.isTraceEnabled() ) {
|
||||||
|
log.trace(
|
||||||
|
"Fetching entity: " +
|
||||||
|
MessageHelper.infoString( this, id, getFactory() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final UniqueEntityLoader loader = getAppropriateLoader( lockRequest, session );
|
||||||
return loader.load( id, optionalObject, session );
|
return loader.load( id, optionalObject, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3208,7 +3249,7 @@ public abstract class AbstractEntityPersister
|
||||||
&& filterHelper.isAffectedBy( session.getLoadQueryInfluencers().getEnabledFilters() );
|
&& filterHelper.isAffectedBy( session.getLoadQueryInfluencers().getEnabledFilters() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private UniqueEntityLoader getAppropriateLoader(LockMode lockMode, SessionImplementor session) {
|
private UniqueEntityLoader getAppropriateLoader(LockRequest lockRequest, SessionImplementor session) {
|
||||||
if ( queryLoader != null ) {
|
if ( queryLoader != null ) {
|
||||||
// if the user specified a custom query loader we need to that
|
// if the user specified a custom query loader we need to that
|
||||||
// regardless of any other consideration
|
// regardless of any other consideration
|
||||||
|
@ -3217,9 +3258,9 @@ public abstract class AbstractEntityPersister
|
||||||
else if ( isAffectedByEnabledFilters( session ) ) {
|
else if ( isAffectedByEnabledFilters( session ) ) {
|
||||||
// because filters affect the rows returned (because they add
|
// because filters affect the rows returned (because they add
|
||||||
// restirctions) these need to be next in precendence
|
// restirctions) these need to be next in precendence
|
||||||
return createEntityLoader( lockMode, session.getLoadQueryInfluencers() );
|
return createEntityLoader( lockRequest, session.getLoadQueryInfluencers() );
|
||||||
}
|
}
|
||||||
else if ( session.getLoadQueryInfluencers().getInternalFetchProfile() != null && LockMode.UPGRADE.greaterThan( lockMode ) ) {
|
else if ( session.getLoadQueryInfluencers().getInternalFetchProfile() != null && LockMode.UPGRADE.greaterThan( lockRequest.getLockMode() ) ) {
|
||||||
// Next, we consider whether an 'internal' fetch profile has been set.
|
// Next, we consider whether an 'internal' fetch profile has been set.
|
||||||
// This indicates a special fetch profile Hibernate needs applied
|
// This indicates a special fetch profile Hibernate needs applied
|
||||||
// (for its merge loading process e.g.).
|
// (for its merge loading process e.g.).
|
||||||
|
@ -3228,10 +3269,10 @@ public abstract class AbstractEntityPersister
|
||||||
else if ( isAffectedByEnabledFetchProfiles( session ) ) {
|
else if ( isAffectedByEnabledFetchProfiles( session ) ) {
|
||||||
// If the session has associated influencers we need to adjust the
|
// If the session has associated influencers we need to adjust the
|
||||||
// SQL query used for loading based on those influencers
|
// SQL query used for loading based on those influencers
|
||||||
return createEntityLoader( lockMode, session.getLoadQueryInfluencers() );
|
return createEntityLoader( lockRequest, session.getLoadQueryInfluencers() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ( UniqueEntityLoader ) loaders.get( lockMode );
|
return ( UniqueEntityLoader ) loaders.get( lockRequest.getLockMode() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.cache.OptimisticCacheSource;
|
import org.hibernate.cache.OptimisticCacheSource;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
|
@ -326,12 +327,24 @@ public interface EntityPersister extends OptimisticCacheSource {
|
||||||
public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session)
|
public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session)
|
||||||
throws HibernateException;
|
throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an instance of the persistent class.
|
||||||
|
*/
|
||||||
|
public Object load(Serializable id, Object optionalObject, LockRequest lockRequest, SessionImplementor session)
|
||||||
|
throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do a version check (optional operation)
|
* Do a version check (optional operation)
|
||||||
*/
|
*/
|
||||||
public void lock(Serializable id, Object version, Object object, LockMode lockMode, SessionImplementor session)
|
public void lock(Serializable id, Object version, Object object, LockMode lockMode, SessionImplementor session)
|
||||||
throws HibernateException;
|
throws HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a version check (optional operation)
|
||||||
|
*/
|
||||||
|
public void lock(Serializable id, Object version, Object object, LockRequest lockRequest, SessionImplementor session)
|
||||||
|
throws HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist an instance
|
* Persist an instance
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
public final class ArrayHelper {
|
public final class ArrayHelper {
|
||||||
|
@ -83,6 +84,12 @@ public final class ArrayHelper {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LockMode[] fillArray(LockRequest lockRequest, int length) {
|
||||||
|
LockMode[] array = new LockMode[length];
|
||||||
|
Arrays.fill(array, lockRequest);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
public static String[] toStringArray(Collection coll) {
|
public static String[] toStringArray(Collection coll) {
|
||||||
return (String[]) coll.toArray( new String[coll.size()] );
|
return (String[]) coll.toArray( new String[coll.size()] );
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.HashMap;
|
||||||
import javax.persistence.EntityNotFoundException;
|
import javax.persistence.EntityNotFoundException;
|
||||||
import javax.persistence.EntityTransaction;
|
import javax.persistence.EntityTransaction;
|
||||||
import javax.persistence.FlushModeType;
|
import javax.persistence.FlushModeType;
|
||||||
|
@ -42,6 +43,7 @@ import javax.persistence.PessimisticLockException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
import javax.persistence.TransactionRequiredException;
|
import javax.persistence.TransactionRequiredException;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
import javax.persistence.PessimisticLockScope;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.metamodel.Metamodel;
|
import javax.persistence.metamodel.Metamodel;
|
||||||
|
@ -74,6 +76,8 @@ import org.hibernate.util.JTAHelper;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable {
|
public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable {
|
||||||
private static final Logger log = LoggerFactory.getLogger( AbstractEntityManagerImpl.class );
|
private static final Logger log = LoggerFactory.getLogger( AbstractEntityManagerImpl.class );
|
||||||
|
private static final String PESSIMISTICLOCKSCOPE = "javax.persistence.lock.scope";
|
||||||
|
private static final String PESSIMISTICLOCKTIMEOUT= "javax.persistence.lock.timeout";
|
||||||
|
|
||||||
private EntityManagerFactoryImpl entityManagerFactory;
|
private EntityManagerFactoryImpl entityManagerFactory;
|
||||||
protected transient TransactionImpl tx = new TransactionImpl( this );
|
protected transient TransactionImpl tx = new TransactionImpl( this );
|
||||||
|
@ -239,19 +243,22 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <A> A find(Class<A> entityClass, Object primaryKey) {
|
public <A> A find(Class<A> entityClass, Object primaryKey) {
|
||||||
LockModeType lmt = null;
|
return find( entityClass, primaryKey, null, null);
|
||||||
return find( entityClass, primaryKey, lmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
|
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
|
||||||
return find(entityClass, primaryKey);
|
return find(entityClass, primaryKey, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) {
|
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) {
|
||||||
|
return find(entityClass, primaryKey, lockModeType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
|
||||||
try {
|
try {
|
||||||
if ( lockModeType != null )
|
if ( lockModeType != null )
|
||||||
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey, getLockMode(lockModeType) );
|
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey, getLockRequest(lockModeType, properties) );
|
||||||
else
|
else
|
||||||
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
|
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
|
||||||
}
|
}
|
||||||
|
@ -277,10 +284,6 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
|
|
||||||
return find(entityClass, primaryKey, lockModeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkTransactionNeeded() {
|
private void checkTransactionNeeded() {
|
||||||
if ( persistenceContextType == PersistenceContextType.TRANSACTION && !isTransactionInProgress() ) {
|
if ( persistenceContextType == PersistenceContextType.TRANSACTION && !isTransactionInProgress() ) {
|
||||||
//no need to mark as rollback, no tx in progress
|
//no need to mark as rollback, no tx in progress
|
||||||
|
@ -334,23 +337,25 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh(Object entity) {
|
public void refresh(Object entity) {
|
||||||
LockModeType lmt = null;
|
refresh(entity, null, null);
|
||||||
refresh(entity, lmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh(Object entity, Map<String, Object> properties) {
|
public void refresh(Object entity, Map<String, Object> properties) {
|
||||||
LockModeType lmt = null;
|
refresh(entity, null, null);
|
||||||
refresh(entity, lmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh(Object entity, LockModeType lockModeType) {
|
public void refresh(Object entity, LockModeType lockModeType) {
|
||||||
|
refresh(entity, lockModeType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
|
||||||
checkTransactionNeeded();
|
checkTransactionNeeded();
|
||||||
try {
|
try {
|
||||||
if ( !getSession().contains( entity ) ) {
|
if ( !getSession().contains( entity ) ) {
|
||||||
throw new IllegalArgumentException( "Entity not managed" );
|
throw new IllegalArgumentException( "Entity not managed" );
|
||||||
}
|
}
|
||||||
if(lockModeType != null)
|
if(lockModeType != null)
|
||||||
getSession().refresh( entity, getLockMode(lockModeType) );
|
getSession().refresh( entity, getLockRequest(lockModeType, properties) );
|
||||||
else
|
else
|
||||||
getSession().refresh( entity );
|
getSession().refresh( entity );
|
||||||
}
|
}
|
||||||
|
@ -362,10 +367,6 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
|
|
||||||
refresh(entity, lockModeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Object entity) {
|
public boolean contains(Object entity) {
|
||||||
try {
|
try {
|
||||||
if ( entity != null
|
if ( entity != null
|
||||||
|
@ -508,6 +509,10 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock(Object entity, LockModeType lockMode) {
|
public void lock(Object entity, LockModeType lockMode) {
|
||||||
|
lock( entity, lockMode, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
|
||||||
try {
|
try {
|
||||||
if ( !isTransactionInProgress() ) {
|
if ( !isTransactionInProgress() ) {
|
||||||
throw new TransactionRequiredException( "no transaction is in progress" );
|
throw new TransactionRequiredException( "no transaction is in progress" );
|
||||||
|
@ -516,21 +521,42 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
if ( !contains( entity ) ) {
|
if ( !contains( entity ) ) {
|
||||||
throw new IllegalArgumentException( "entity not in the persistence context" );
|
throw new IllegalArgumentException( "entity not in the persistence context" );
|
||||||
}
|
}
|
||||||
getSession().lock( entity, getLockMode( lockMode ) );
|
getSession().lock( entity, getLockRequest(lockModeType, properties) );
|
||||||
}
|
}
|
||||||
catch ( HibernateException he ) {
|
catch ( HibernateException he ) {
|
||||||
throw convert( he );
|
throw convert( he );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock(Object o, LockModeType lockModeType, Map<String, Object> properties) {
|
private LockRequest getLockRequest(LockModeType lockModeType, Map<String, Object> properties) {
|
||||||
// todo: support different properties passed in
|
LockRequest lockRequest = new LockRequest();
|
||||||
lock(o,lockModeType);
|
lockRequest.setLockMode(getLockMode(lockModeType));
|
||||||
|
if ( properties != null ) {
|
||||||
|
// lockRequest scope will default to false (PessimisticLockScope.NORMAL)
|
||||||
|
Object value = properties.get(PESSIMISTICLOCKSCOPE);
|
||||||
|
if ( value instanceof String && PessimisticLockScope.valueOf((String) value) == PessimisticLockScope.EXTENDED) {
|
||||||
|
lockRequest.setScope(true);
|
||||||
|
}
|
||||||
|
// lockRequest timeout will default to LockRequest.FOREVER_WAIT
|
||||||
|
value = properties.get(PESSIMISTICLOCKTIMEOUT);
|
||||||
|
if ( value instanceof String ) {
|
||||||
|
int timeout = Integer.parseInt((String) value);
|
||||||
|
if ( timeout < 0 ) {
|
||||||
|
lockRequest.setTimeOut(LockRequest.WAIT_FOREVER);
|
||||||
|
}
|
||||||
|
else if( timeout == 0 ) {
|
||||||
|
lockRequest.setTimeOut(LockRequest.NO_WAIT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lockRequest.setTimeOut(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lockRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LockModeType getLockModeType(LockMode lockMode) {
|
||||||
private LockModeType getLockModeType(LockMode lockMode)
|
|
||||||
{
|
|
||||||
if ( lockMode == LockMode.NONE )
|
if ( lockMode == LockMode.NONE )
|
||||||
return LockModeType.NONE;
|
return LockModeType.NONE;
|
||||||
else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ )
|
else if ( lockMode == LockMode.OPTIMISTIC || lockMode == LockMode.READ )
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.Hibernate;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.LockRequest;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.cache.CacheConcurrencyStrategy;
|
import org.hibernate.cache.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
|
@ -279,6 +280,18 @@ public class CustomPersister implements EntityPersister {
|
||||||
return GENERATOR;
|
return GENERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see EntityPersister#load(Serializable, Object, LockRequest, SessionImplementor)
|
||||||
|
*/
|
||||||
|
public Object load(
|
||||||
|
Serializable id,
|
||||||
|
Object optionalObject,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionImplementor session
|
||||||
|
) throws HibernateException {
|
||||||
|
return load(id, optionalObject, lockRequest.getLockMode(), session);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see EntityPersister#load(Serializable, Object, LockMode, SessionImplementor)
|
* @see EntityPersister#load(Serializable, Object, LockMode, SessionImplementor)
|
||||||
*/
|
*/
|
||||||
|
@ -323,6 +336,20 @@ public class CustomPersister implements EntityPersister {
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see EntityPersister#lock(Serializable, Object, Object, LockMode, SessionImplementor)
|
||||||
|
*/
|
||||||
|
public void lock(
|
||||||
|
Serializable id,
|
||||||
|
Object version,
|
||||||
|
Object object,
|
||||||
|
LockRequest lockRequest,
|
||||||
|
SessionImplementor session
|
||||||
|
) throws HibernateException {
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see EntityPersister#lock(Serializable, Object, Object, LockMode, SessionImplementor)
|
* @see EntityPersister#lock(Serializable, Object, Object, LockMode, SessionImplementor)
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue