Hibernate SVN: r10949 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/event/def test/org/hibernate/test/propertyref/basic
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 16:53:41 -0500 (Thu, 07 Dec 2006)
New Revision: 10949
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
Log:
HHH-2291 - reattachment of collections with a property-ref key;
code and javadoc cleanup
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -5,7 +5,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
import org.hibernate.LockMode;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.EntityKey;
@@ -25,7 +25,7 @@
*/
public class AbstractReassociateEventListener implements Serializable {
- private static final Log log = LogFactory.getLog(AbstractReassociateEventListener.class);
+ private static final Log log = LogFactory.getLog( AbstractReassociateEventListener.class );
/**
* Associates a given entity (either transient or associated with another session) to
@@ -35,52 +35,53 @@
* @param object The entity to be associated
* @param id The id of the entity.
* @param persister The entity's persister instance.
+ *
* @return An EntityEntry representing the entity within this session.
- * @throws HibernateException
*/
- protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister)
- throws HibernateException {
-
- if ( log.isTraceEnabled() ) log.trace(
- "reassociating transient instance: " +
- MessageHelper.infoString( persister, id, event.getSession().getFactory() )
+ protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister) {
+
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ "reassociating transient instance: " +
+ MessageHelper.infoString( persister, id, event.getSession().getFactory() )
);
-
+ }
+
EventSource source = event.getSession();
EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
-
- source.getPersistenceContext().checkUniqueness(key, object);
-
+
+ source.getPersistenceContext().checkUniqueness( key, object );
+
//get a snapshot
Object[] values = persister.getPropertyValues( object, source.getEntityMode() );
- TypeFactory.deepCopy(
- values,
- persister.getPropertyTypes(),
- persister.getPropertyUpdateability(),
- values,
- source
- );
- Object version = Versioning.getVersion(values, persister);
-
+ TypeFactory.deepCopy(
+ values,
+ persister.getPropertyTypes(),
+ persister.getPropertyUpdateability(),
+ values,
+ source
+ );
+ Object version = Versioning.getVersion( values, persister );
+
EntityEntry newEntry = source.getPersistenceContext().addEntity(
- object,
- Status.MANAGED,
- values,
- key,
- version,
- LockMode.NONE,
- true,
- persister,
- false,
+ object,
+ Status.MANAGED,
+ values,
+ key,
+ version,
+ LockMode.NONE,
+ true,
+ persister,
+ false,
true //will be ignored, using the existing Entry instead
- );
-
- new OnLockVisitor( source, id ).process( object, persister );
-
+ );
+
+ new OnLockVisitor( source, id, object ).process( object, persister );
+
persister.afterReassociate( object, source );
-
+
return newEntry;
-
+
}
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -6,7 +6,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.action.EntityIdentityInsertAction;
@@ -44,60 +44,59 @@
protected static final int DETACHED = 2;
protected static final int DELETED = 3;
- private static final Log log = LogFactory.getLog(AbstractSaveEventListener.class);
+ private static final Log log = LogFactory.getLog( AbstractSaveEventListener.class );
/**
* Prepares the save call using the given requested id.
+ *
* @param entity The entity to be saved.
* @param requestedId The id to which to associate the entity.
+ * @param entityName The name of the entity being saved.
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
+ *
* @return The id used to save the entity.
- * @throws HibernateException
*/
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
- EventSource source)
- throws HibernateException {
+ EventSource source) {
return performSave(
entity,
requestedId,
- source.getEntityPersister(entityName, entity),
+ source.getEntityPersister( entityName, entity ),
false,
anything,
source,
- true
- );
+ true
+ );
}
/**
* Prepares the save call using a newly generated id.
+ *
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
-
- EntityPersister persister = source.getEntityPersister(entityName, entity);
-
- Serializable generatedId = persister.getIdentifierGenerator()
- .generate( source, entity );
-
+ boolean requiresImmediateIdAccess) {
+ EntityPersister persister = source.getEntityPersister( entityName, entity );
+ Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() );
}
@@ -108,16 +107,17 @@
return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess );
}
else {
-
+
if ( log.isDebugEnabled() ) {
log.debug(
- "generated identifier: " +
- persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ) +
- ", using strategy: " +
- persister.getIdentifierGenerator().getClass().getName() //TODO: define toString()s for generators
- );
+ "generated identifier: " +
+ persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ) +
+ ", using strategy: " +
+ persister.getIdentifierGenerator().getClass().getName()
+ //TODO: define toString()s for generators
+ );
}
-
+
return performSave( entity, generatedId, persister, false, anything, source, true );
}
}
@@ -125,18 +125,20 @@
/**
* Ppepares the save call by checking the session caches for a pre-existing
* entity and performing any lifecycle callbacks.
+ *
* @param entity The entity to be saved.
* @param id The id by which to save the entity.
* @param persister The entity's persister instance.
- * @param useIdentityColumn Is an identity column in use?
+ * @param useIdentityColumn Is an identity column being used?
+ * @param anything Generally cascade-specific information.
* @param source The session from which the event originated.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable performSave(
Object entity,
@@ -145,55 +147,54 @@
boolean useIdentityColumn,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
+ boolean requiresImmediateIdAccess) {
if ( log.isTraceEnabled() ) {
- log.trace(
- "saving " +
- MessageHelper.infoString( persister, id, source.getFactory() )
- );
+ log.trace(
+ "saving " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
-
+
EntityKey key;
if ( !useIdentityColumn ) {
key = new EntityKey( id, persister, source.getEntityMode() );
- Object old = source.getPersistenceContext().getEntity(key);
- if (old != null) {
- if ( source.getPersistenceContext().getEntry(old).getStatus() == Status.DELETED ) {
- source.forceFlush( source.getPersistenceContext().getEntry(old) );
+ Object old = source.getPersistenceContext().getEntity( key );
+ if ( old != null ) {
+ if ( source.getPersistenceContext().getEntry( old ).getStatus() == Status.DELETED ) {
+ source.forceFlush( source.getPersistenceContext().getEntry( old ) );
}
else {
throw new NonUniqueObjectException( id, persister.getEntityName() );
}
}
- persister.setIdentifier(entity, id, source.getEntityMode());
+ persister.setIdentifier( entity, id, source.getEntityMode() );
}
else {
key = null;
}
-
- if ( invokeSaveLifecycle(entity, persister, source) ) {
+
+ if ( invokeSaveLifecycle( entity, persister, source ) ) {
return id; //EARLY EXIT
}
return performSaveOrReplicate(
- entity,
- key,
- persister,
- useIdentityColumn,
- anything,
+ entity,
+ key,
+ persister,
+ useIdentityColumn,
+ anything,
source,
- requiresImmediateIdAccess
- );
+ requiresImmediateIdAccess
+ );
}
-
+
protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) {
// Sub-insertions should occur before containing insertion so
// Try to do the callback now
if ( persister.implementsLifecycle( source.getEntityMode() ) ) {
log.debug( "calling onSave()" );
- if ( ( (Lifecycle) entity ).onSave(source) ) {
+ if ( ( ( Lifecycle ) entity ).onSave( source ) ) {
log.debug( "insertion vetoed by onSave()" );
return true;
}
@@ -203,21 +204,25 @@
protected void validate(Object entity, EntityPersister persister, EventSource source) {
if ( persister.implementsValidatable( source.getEntityMode() ) ) {
- ( ( Validatable ) entity ).validate();
- }
+ ( ( Validatable ) entity ).validate();
+ }
}
/**
* Performs all the actual work needed to save an entity (well to get the save moved to
* the execution queue).
+ *
* @param entity The entity to be saved
* @param key The id to be used for saving the entity (or null, in the case of identity columns)
* @param persister The entity's persister instance.
* @param useIdentityColumn Should an identity column be used for id generation?
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of the current event.
+ * @param requiresImmediateIdAccess Is access to the identifier required immediately
+ * after the completion of the save? persist(), for example, does not require this...
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable performSaveOrReplicate(
Object entity,
@@ -226,18 +231,17 @@
boolean useIdentityColumn,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
-
+ boolean requiresImmediateIdAccess) {
+
validate( entity, persister, source );
- Serializable id = key==null ? null : key.getIdentifier();
+ Serializable id = key == null ? null : key.getIdentifier();
boolean inTxn = source.getJDBCContext().isTransactionInProgress();
boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
if ( useIdentityColumn && !shouldDelayIdentityInserts ) {
- log.trace("executing insertions");
+ log.trace( "executing insertions" );
source.getActionQueue().executeInserts();
}
@@ -253,46 +257,50 @@
null,
LockMode.WRITE,
useIdentityColumn,
- persister,
- false,
+ persister,
+ false,
false
- );
+ );
- cascadeBeforeSave(source, persister, entity, anything);
+ cascadeBeforeSave( source, persister, entity, anything );
- Object[] values = persister.getPropertyValuesToInsert(entity, getMergeMap(anything), source);
+ Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source );
Type[] types = persister.getPropertyTypes();
- boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source);
+ boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
if ( persister.hasCollections() ) {
- substitute = substitute || visitCollectionsBeforeSave(id, values, types, source);
+ substitute = substitute || visitCollectionsBeforeSave( entity, id, values, types, source );
}
- if (substitute) persister.setPropertyValues( entity, values, source.getEntityMode() );
+ if ( substitute ) {
+ persister.setPropertyValues( entity, values, source.getEntityMode() );
+ }
- TypeFactory.deepCopy(
- values,
- types,
- persister.getPropertyUpdateability(),
- values,
+ TypeFactory.deepCopy(
+ values,
+ types,
+ persister.getPropertyUpdateability(),
+ values,
source
+ );
+
+ new ForeignKeys.Nullifier( entity, false, useIdentityColumn, source )
+ .nullifyTransientReferences( values, types );
+ new Nullability( source ).checkNullability( values, persister, false );
+
+ if ( useIdentityColumn ) {
+ EntityIdentityInsertAction insert = new EntityIdentityInsertAction(
+ values, entity, persister, source, shouldDelayIdentityInserts
);
-
- new ForeignKeys.Nullifier(entity, false, useIdentityColumn, source)
- .nullifyTransientReferences(values, types);
- new Nullability(source).checkNullability( values, persister, false );
-
- if ( useIdentityColumn ) {
- EntityIdentityInsertAction insert = new EntityIdentityInsertAction( values, entity, persister, source, shouldDelayIdentityInserts );
- if ( ! shouldDelayIdentityInserts ) {
+ if ( !shouldDelayIdentityInserts ) {
log.debug( "executing identity-insert immediately" );
- source.getActionQueue().execute(insert);
+ source.getActionQueue().execute( insert );
id = insert.getGeneratedId();
//now done in EntityIdentityInsertAction
//persister.setIdentifier( entity, id, source.getEntityMode() );
key = new EntityKey( id, persister, source.getEntityMode() );
- source.getPersistenceContext().checkUniqueness(key, entity);
+ source.getPersistenceContext().checkUniqueness( key, entity );
//source.getBatcher().executeBatch(); //found another way to ensure that all batched joined inserts have been executed
}
else {
@@ -302,7 +310,7 @@
}
}
- Object version = Versioning.getVersion(values, persister);
+ Object version = Versioning.getVersion( values, persister );
source.getPersistenceContext().addEntity(
entity,
Status.MANAGED,
@@ -312,18 +320,18 @@
LockMode.WRITE,
useIdentityColumn,
persister,
- isVersionIncrementDisabled(),
+ isVersionIncrementDisabled(),
false
- );
+ );
//source.getPersistenceContext().removeNonExist( new EntityKey( id, persister, source.getEntityMode() ) );
if ( !useIdentityColumn ) {
- source.getActionQueue().addAction(
- new EntityInsertAction(id, values, entity, version, persister, source)
- );
+ source.getActionQueue().addAction(
+ new EntityInsertAction( id, values, entity, version, persister, source )
+ );
}
- cascadeAfterSave(source, persister, entity, anything);
+ cascadeAfterSave( source, persister, entity, anything );
markInterceptorDirty( entity, persister, source );
@@ -333,7 +341,7 @@
private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.injectFieldInterceptor(
- entity,
+ entity,
persister.getEntityName(),
null,
source
@@ -341,44 +349,55 @@
interceptor.dirty();
}
}
-
+
protected Map getMergeMap(Object anything) {
return null;
}
-
+
/**
* After the save, will te version number be incremented
* if the instance is modified?
+ *
+ * @return True if the version will be incremented on an entity change after save;
+ * false otherwise.
*/
protected boolean isVersionIncrementDisabled() {
return false;
}
-
- protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
- WrapVisitor visitor = new WrapVisitor(source);
+
+ protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
+ WrapVisitor visitor = new WrapVisitor( source );
// substitutes into values by side-effect
- visitor.processEntityPropertyValues(values, types);
+ visitor.processEntityPropertyValues( values, types );
return visitor.isSubstitutionRequired();
}
-
+
/**
* Perform any property value substitution that is necessary
* (interceptor callback, version initialization...)
+ *
+ * @param entity The entity
+ * @param id The entity identifier
+ * @param values The snapshot entity state
+ * @param persister The entity persister
+ * @param source The originating session
+ *
+ * @return True if the snapshot state changed such that
+ * reinjection of the values into the entity is required.
*/
protected boolean substituteValuesIfNecessary(
- Object entity,
- Serializable id,
- Object[] values,
+ Object entity,
+ Serializable id,
+ Object[] values,
EntityPersister persister,
- SessionImplementor source
- ) {
+ SessionImplementor source) {
boolean substitute = source.getInterceptor().onSave(
entity,
id,
values,
persister.getPropertyNames(),
persister.getPropertyTypes()
- );
+ );
//keep the existing version number in the case of replicate!
if ( persister.isVersioned() ) {
@@ -386,7 +405,7 @@
values,
persister.getVersionProperty(),
persister.getVersionType(),
- source
+ source
) || substitute;
}
return substitute;
@@ -394,23 +413,23 @@
/**
* Handles the calls needed to perform pre-save cascades for the given entity.
+ *
* @param source The session from whcih the save event originated.
* @param persister The entity's persister instance.
* @param entity The entity to be saved.
- * @throws HibernateException
+ * @param anything Generally cascade-specific data
*/
protected void cascadeBeforeSave(
EventSource source,
EntityPersister persister,
Object entity,
- Object anything)
- throws HibernateException {
+ Object anything) {
// cascade-save to many-to-one BEFORE the parent is saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), Cascade.BEFORE_INSERT_AFTER_DELETE, source )
- .cascade(persister, entity, anything);
+ .cascade( persister, entity, anything );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
@@ -419,97 +438,103 @@
/**
* Handles to calls needed to perform post-save cascades.
+ *
* @param source The session from which the event originated.
* @param persister The entity's persister instance.
* @param entity The entity beng saved.
- * @throws HibernateException
+ * @param anything Generally cascade-specific data
*/
protected void cascadeAfterSave(
EventSource source,
- EntityPersister persister,
- Object entity,
- Object anything)
- throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ Object anything) {
// cascade-save to collections AFTER the collection owner was saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), Cascade.AFTER_INSERT_BEFORE_DELETE, source )
- .cascade(persister, entity, anything);
+ .cascade( persister, entity, anything );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
}
}
-
+
protected abstract CascadingAction getCascadeAction();
-
+
/**
* Determine whether the entity is persistent, detached, or transient
+ *
+ * @param entity The entity to check
+ * @param entityName The name of the entity
+ * @param entry The entity's entry in the persistence context
+ * @param source The originating session.
+ *
+ * @return The state.
*/
protected int getEntityState(
- Object entity,
- String entityName,
+ Object entity,
+ String entityName,
EntityEntry entry, //pass this as an argument only to avoid double looking
- SessionImplementor source
- ) {
-
- if ( entry!=null ) { // the object is persistent
-
+ SessionImplementor source) {
+
+ if ( entry != null ) { // the object is persistent
+
//the entity is associated with the session, so check its status
if ( entry.getStatus() != Status.DELETED ) {
// do nothing for persistent instances
if ( log.isTraceEnabled() ) {
- log.trace(
- "persistent instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "persistent instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return PERSISTENT;
}
- else {
+ else {
//ie. e.status==DELETED
if ( log.isTraceEnabled() ) {
- log.trace(
- "deleted instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "deleted instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return DELETED;
}
-
+
}
else { // the object is transient or detached
-
+
//the entity is not associated with the session, so
//try interceptor and unsaved-value
-
+
if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) {
if ( log.isTraceEnabled() ) {
- log.trace(
- "transient instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "transient instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return TRANSIENT;
}
else {
if ( log.isTraceEnabled() ) {
- log.trace(
- "detached instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "detached instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return DETACHED;
}
}
}
-
+
protected String getLoggableName(String entityName, Object entity) {
- return entityName==null ? entity.getClass().getName() : entityName;
+ return entityName == null ? entity.getClass().getName() : entityName;
}
-
+
protected Boolean getAssumedUnsaved() {
return null;
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -6,6 +6,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.hibernate.CacheMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
@@ -38,21 +39,31 @@
*/
public class DefaultDeleteEventListener implements DeleteEventListener {
- private static final Log log = LogFactory.getLog(DefaultDeleteEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultDeleteEventListener.class );
- /** Handle the given delete event.
- *
- * @param event The delete event to be handled.
- * @throws HibernateException
- */
+ /**
+ * Handle the given delete event.
+ *
+ * @param event The delete event to be handled.
+ *
+ * @throws HibernateException
+ */
public void onDelete(DeleteEvent event) throws HibernateException {
onDelete( event, new IdentitySet() );
}
+ /**
+ * Handle the given delete event. This is the cascaded form.
+ *
+ * @param event The delete event.
+ * @param transientEntities The cache of entities already deleted
+ *
+ * @throws HibernateException
+ */
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException {
final EventSource source = event.getSession();
-
+
final PersistenceContext persistenceContext = source.getPersistenceContext();
Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
@@ -79,16 +90,16 @@
if ( id == null ) {
throw new TransientObjectException(
- "the detached instance passed to delete() had a null identifier"
+ "the detached instance passed to delete() had a null identifier"
);
}
-
+
EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
- persistenceContext.checkUniqueness(key, entity);
+ persistenceContext.checkUniqueness( key, entity );
- new OnUpdateVisitor( source, id ).process( entity, persister );
-
+ new OnUpdateVisitor( source, id, entity ).process( entity, persister );
+
version = persister.getVersion( entity, source.getEntityMode() );
entityEntry = persistenceContext.addEntity(
@@ -102,7 +113,7 @@
persister,
false,
false
- );
+ );
}
else {
log.trace( "deleting a persistent instance" );
@@ -123,7 +134,9 @@
);
}*/
- if ( invokeDeleteLifecycle( source, entity, persister ) ) return;
+ if ( invokeDeleteLifecycle( source, entity, persister ) ) {
+ return;
+ }
deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister, transientEntities );
@@ -132,6 +145,14 @@
}
}
+ /**
+ * Called when we have recognized an attempt to delete a detached entity.
+ * <p/>
+ * This is perfectly valid in Hibernate usage; JPA, however, forbids this.
+ * Thus, this is a hook for HEM to affect this behavior.
+ *
+ * @param event The event.
+ */
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
// ok in normal Hibernate usage to delete a detached entity; JPA however
// forbids it, thus this is a hook for HEM to affect this behavior
@@ -168,19 +189,31 @@
cascadeAfterDelete( session, persister, entity, transientEntities );
}
+ /**
+ * Perform the entity deletion. Well, as with most operations, does not
+ * really perform it; just schedules an action/execution with the
+ * {@link org.hibernate.engine.ActionQueue} for execution during flush.
+ *
+ * @param session The originating session
+ * @param entity The entity to delete
+ * @param entityEntry The entity's entry in the {@link PersistenceContext}
+ * @param isCascadeDeleteEnabled Is delete cascading enabled?
+ * @param persister The entity persister.
+ * @param transientEntities A cache of already deleted entities.
+ */
protected final void deleteEntity(
- final EventSource session,
- final Object entity,
- final EntityEntry entityEntry,
- final boolean isCascadeDeleteEnabled,
- final EntityPersister persister,
- final Set transientEntities) throws HibernateException {
+ final EventSource session,
+ final Object entity,
+ final EntityEntry entityEntry,
+ final boolean isCascadeDeleteEnabled,
+ final EntityPersister persister,
+ final Set transientEntities) {
if ( log.isTraceEnabled() ) {
log.trace(
"deleting " +
- MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
- );
+ MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
+ );
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
@@ -196,7 +229,7 @@
}
final Object[] deletedState = createDeletedState( persister, currentState, session );
- entityEntry.setDeletedState(deletedState);
+ entityEntry.setDeletedState( deletedState );
session.getInterceptor().onDelete(
entity,
@@ -207,15 +240,15 @@
);
// before any callbacks, etc, so subdeletions see that this deletion happened first
- persistenceContext.setEntryStatus(entityEntry, Status.DELETED);
- EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );
+ persistenceContext.setEntryStatus( entityEntry, Status.DELETED );
+ EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );
cascadeBeforeDelete( session, persister, entity, entityEntry, transientEntities );
- new ForeignKeys.Nullifier(entity, true, false, session)
+ new ForeignKeys.Nullifier( entity, true, false, session )
.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
- new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true );
- persistenceContext.getNullifiableEntityKeys().add(key);
+ new Nullability( session ).checkNullability( entityEntry.getDeletedState(), persister, true );
+ persistenceContext.getNullifiableEntityKeys().add( key );
// Ensures that containing deletions happen before sub-deletions
session.getActionQueue().addAction(
@@ -251,23 +284,23 @@
protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
if ( persister.implementsLifecycle( session.getEntityMode() ) ) {
log.debug( "calling onDelete()" );
- if ( ( (Lifecycle) entity ).onDelete(session) ) {
- log.debug("deletion vetoed by onDelete()");
+ if ( ( ( Lifecycle ) entity ).onDelete( session ) ) {
+ log.debug( "deletion vetoed by onDelete()" );
return true;
}
}
return false;
}
-
+
protected void cascadeBeforeDelete(
EventSource session,
- EntityPersister persister,
- Object entity,
- EntityEntry entityEntry,
- Set transientEntities) throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ EntityEntry entityEntry,
+ Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
- session.setCacheMode(CacheMode.GET);
+ session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to collections BEFORE the collection owner is deleted
@@ -276,18 +309,18 @@
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
- session.setCacheMode(cacheMode);
+ session.setCacheMode( cacheMode );
}
}
protected void cascadeAfterDelete(
EventSource session,
- EntityPersister persister,
- Object entity,
- Set transientEntities) throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
- session.setCacheMode(CacheMode.GET);
+ session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to many-to-one AFTER the parent was deleted
@@ -296,7 +329,7 @@
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
- session.setCacheMode(cacheMode);
+ session.setCacheMode( cacheMode );
}
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -30,44 +30,43 @@
*/
public class DefaultReplicateEventListener extends AbstractSaveEventListener implements ReplicateEventListener {
- private static final Log log = LogFactory.getLog(DefaultReplicateEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultReplicateEventListener.class );
- /**
+ /**
* Handle the given replicate event.
*
* @param event The replicate event to be handled.
- * @throws HibernateException
+ *
+ * @throws TransientObjectException An invalid attempt to replicate a transient entity.
*/
- public void onReplicate(ReplicateEvent event) throws HibernateException {
-
+ public void onReplicate(ReplicateEvent event) {
final EventSource source = event.getSession();
-
if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
- log.trace("uninitialized proxy passed to replicate()");
+ log.trace( "uninitialized proxy passed to replicate()" );
return;
}
Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );
- if ( source.getPersistenceContext().isEntryFor(entity) ) {
- log.trace("ignoring persistent instance passed to replicate()");
+ if ( source.getPersistenceContext().isEntryFor( entity ) ) {
+ log.trace( "ignoring persistent instance passed to replicate()" );
//hum ... should we cascade anyway? throw an exception? fine like it is?
return;
}
EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
-
+
// get the id from the object
/*if ( persister.isUnsaved(entity, source) ) {
throw new TransientObjectException("transient instance passed to replicate()");
}*/
Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
- if (id==null) {
- throw new TransientObjectException("instance with null id passed to replicate()");
+ if ( id == null ) {
+ throw new TransientObjectException( "instance with null id passed to replicate()" );
}
final ReplicationMode replicationMode = event.getReplicationMode();
-
+
final Object oldVersion;
if ( replicationMode == ReplicationMode.EXCEPTION ) {
//always do an INSERT, and let it fail by constraint violation
@@ -75,14 +74,16 @@
}
else {
//what is the version on the database?
- oldVersion = persister.getCurrentVersion(id, source);
+ oldVersion = persister.getCurrentVersion( id, source );
}
- if ( oldVersion!=null ) {
+ if ( oldVersion != null ) {
//existing row - do an update if appropriate
if ( log.isTraceEnabled() ) {
- log.trace( "found existing row for " +
- MessageHelper.infoString( persister, id, source.getFactory() ) );
+ log.trace(
+ "found existing row for " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
@@ -92,26 +93,28 @@
persister.getVersionType()
);
- if (canReplicate) {
+ if ( canReplicate ) {
//will result in a SQL UPDATE:
- performReplication(entity, id, oldVersion, persister, replicationMode, source);
+ performReplication( entity, id, oldVersion, persister, replicationMode, source );
}
else {
//else do nothing (don't even reassociate object!)
- log.trace("no need to replicate");
+ log.trace( "no need to replicate" );
}
-
+
//TODO: would it be better to do a refresh from db?
}
else {
// no existing row - do an insert
if ( log.isTraceEnabled() ) {
- log.trace( "no existing row, replicating new instance " +
- MessageHelper.infoString( persister, id, source.getFactory() ) );
+ log.trace(
+ "no existing row, replicating new instance " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
- final EntityKey key = regenerate ?
+ final EntityKey key = regenerate ?
null : new EntityKey( id, persister, source.getEntityMode() );
performSaveOrReplicate(
@@ -121,77 +124,74 @@
regenerate,
replicationMode,
source,
- true
+ true
);
}
}
- protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
+ protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
//TODO: we use two visitors here, inefficient!
- OnReplicateVisitor visitor = new OnReplicateVisitor(source, id, false);
- visitor.processEntityPropertyValues(values, types);
- return super.visitCollectionsBeforeSave(id, values, types, source);
+ OnReplicateVisitor visitor = new OnReplicateVisitor( source, id, entity, false );
+ visitor.processEntityPropertyValues( values, types );
+ return super.visitCollectionsBeforeSave( entity, id, values, types, source );
}
protected boolean substituteValuesIfNecessary(
- Object entity,
- Serializable id,
- Object[] values,
+ Object entity,
+ Serializable id,
+ Object[] values,
EntityPersister persister,
- SessionImplementor source
- ) {
+ SessionImplementor source) {
return false;
}
-
+
protected boolean isVersionIncrementDisabled() {
return true;
}
-
- private final void performReplication(
+
+ private void performReplication(
Object entity,
Serializable id,
Object version,
EntityPersister persister,
ReplicationMode replicationMode,
- EventSource source)
- throws HibernateException {
+ EventSource source) throws HibernateException {
if ( log.isTraceEnabled() ) {
- log.trace(
- "replicating changes to " +
- MessageHelper.infoString( persister, id, source.getFactory() )
+ log.trace(
+ "replicating changes to " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
);
}
- new OnReplicateVisitor(source, id, true).process( entity, persister );
+ new OnReplicateVisitor( source, id, entity, true ).process( entity, persister );
- source.getPersistenceContext().addEntity(
- entity,
- Status.MANAGED,
- null,
- new EntityKey( id, persister, source.getEntityMode() ),
- version,
- LockMode.NONE,
- true,
- persister,
- true,
+ source.getPersistenceContext().addEntity(
+ entity,
+ Status.MANAGED,
+ null,
+ new EntityKey( id, persister, source.getEntityMode() ),
+ version,
+ LockMode.NONE,
+ true,
+ persister,
+ true,
false
- );
+ );
cascadeAfterReplicate( entity, persister, replicationMode, source );
}
private void cascadeAfterReplicate(
- Object entity,
- EntityPersister persister,
- ReplicationMode replicationMode,
- EventSource source
- ) {
+ Object entity,
+ EntityPersister persister,
+ ReplicationMode replicationMode,
+ EventSource source) {
source.getPersistenceContext().incrementCascadeLevel();
try {
- new Cascade(CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source)
- .cascade(persister, entity, replicationMode);
+ new Cascade( CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source )
+ .cascade( persister, entity, replicationMode );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -5,6 +5,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
@@ -27,218 +28,240 @@
import org.hibernate.proxy.HibernateProxy;
/**
- * Defines the default update event listener used by hibernate for updating
- * transient entities in response to generated update events.
+ * Defines the default listener used by Hibernate for handling save-update
+ * events.
*
- * @author Steve Ebersole, Gavin King
+ * @author Steve Ebersole
+ * @author Gavin King
*/
public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener {
- private static final Log log = LogFactory.getLog(DefaultSaveOrUpdateEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultSaveOrUpdateEventListener.class );
- /**
+ /**
* Handle the given update event.
*
* @param event The update event to be handled.
- * @throws HibernateException
*/
- public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException {
-
+ public void onSaveOrUpdate(SaveOrUpdateEvent event) {
final SessionImplementor source = event.getSession();
final Object object = event.getObject();
+ final Serializable requestedId = event.getRequestedId();
- final Serializable requestedId = event.getRequestedId();
- if ( requestedId!=null ) {
+ if ( requestedId != null ) {
//assign the requested id to the proxy, *before*
//reassociating the proxy
if ( object instanceof HibernateProxy ) {
- ( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier(requestedId);
+ ( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId );
}
}
-
- if ( reassociateIfUninitializedProxy(object, source) ) {
- log.trace("reassociated uninitialized proxy");
+
+ if ( reassociateIfUninitializedProxy( object, source ) ) {
+ log.trace( "reassociated uninitialized proxy" );
// an uninitialized proxy, noop, don't even need to
// return an id, since it is never a save()
}
else {
//initialize properties of the event:
- final Object entity = source.getPersistenceContext().unproxyAndReassociate(object);
- event.setEntity(entity);
- event.setEntry( source.getPersistenceContext().getEntry(entity) );
+ final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );
+ event.setEntity( entity );
+ event.setEntry( source.getPersistenceContext().getEntry( entity ) );
//return the id in the event object
- event.setResultId( performSaveOrUpdate(event) );
+ event.setResultId( performSaveOrUpdate( event ) );
}
-
+
}
-
+
protected boolean reassociateIfUninitializedProxy(Object object, SessionImplementor source) {
- return source.getPersistenceContext().reassociateIfUninitializedProxy(object);
+ return source.getPersistenceContext().reassociateIfUninitializedProxy( object );
}
-
+
protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) {
-
- // use various roles to determine if the instance is
- // transient, persistent or detached:
-
- int entityState = getEntityState(
- event.getEntity(),
- event.getEntityName(),
- event.getEntry(),
- event.getSession()
- );
-
- switch (entityState) {
- case DETACHED:
- entityIsDetached(event);
+ int entityState = getEntityState(
+ event.getEntity(),
+ event.getEntityName(),
+ event.getEntry(),
+ event.getSession()
+ );
+
+ switch ( entityState ) {
+ case DETACHED:
+ entityIsDetached( event );
return null;
case PERSISTENT:
- return entityIsPersistent(event);
+ return entityIsPersistent( event );
default: //TRANSIENT or DELETED
- return entityIsTransient(event);
+ return entityIsTransient( event );
}
-
}
-
+
protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("ignoring persistent instance");
-
+ log.trace( "ignoring persistent instance" );
+
EntityEntry entityEntry = event.getEntry();
- if ( entityEntry==null ) {
- throw new AssertionFailure("entity was transient or detached");
+ if ( entityEntry == null ) {
+ throw new AssertionFailure( "entity was transient or detached" );
}
else {
-
+
if ( entityEntry.getStatus() == Status.DELETED ) {
- throw new AssertionFailure("entity was deleted");
+ throw new AssertionFailure( "entity was deleted" );
}
-
+
final SessionFactoryImplementor factory = event.getSession().getFactory();
Serializable requestedId = event.getRequestedId();
-
+
Serializable savedId;
if ( requestedId == null ) {
savedId = entityEntry.getId();
}
else {
-
+
final boolean isEqual = !entityEntry.getPersister().getIdentifierType()
.isEqual( requestedId, entityEntry.getId(), event.getSession().getEntityMode(), factory );
-
+
if ( isEqual ) {
throw new PersistentObjectException(
"object passed to save() was already persistent: " +
- MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
- );
+ MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
+ );
}
-
+
savedId = requestedId;
-
+
}
-
+
if ( log.isTraceEnabled() ) {
- log.trace(
- "object already associated with session: " +
- MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
- );
+ log.trace(
+ "object already associated with session: " +
+ MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
+ );
}
-
+
return savedId;
-
+
}
}
-
- /**
- * Handle the given save event.
+
+ /**
+ * The given save-update event named a transient entity.
+ * <p/>
+ * Here, we will perform the save processing.
*
* @param event The save event to be handled.
- * @throws HibernateException
+ *
+ * @return The entity's identifier after saving.
*/
- protected Serializable entityIsTransient(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("saving transient instance");
+ protected Serializable entityIsTransient(SaveOrUpdateEvent event) {
- final EventSource source = event.getSession();
+ log.trace( "saving transient instance" );
+ final EventSource source = event.getSession();
+
EntityEntry entityEntry = event.getEntry();
if ( entityEntry != null ) {
if ( entityEntry.getStatus() == Status.DELETED ) {
- source.forceFlush(entityEntry);
+ source.forceFlush( entityEntry );
}
else {
- throw new AssertionFailure("entity was persistent");
+ throw new AssertionFailure( "entity was persistent" );
}
}
-
- Serializable id = saveWithGeneratedOrRequestedId(event);
+ Serializable id = saveWithGeneratedOrRequestedId( event );
+
source.getPersistenceContext().reassociateProxy( event.getObject(), id );
-
+
return id;
}
-
+
/**
* Save the transient instance, assigning the right identifier
+ *
+ * @param event The initiating event.
+ *
+ * @return The entity's identifier value after saving.
*/
protected Serializable saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) {
return saveWithGeneratedId(
- event.getEntity(),
- event.getEntityName(),
- null,
+ event.getEntity(),
+ event.getEntityName(),
+ null,
event.getSession(),
- true
+ true
);
}
-
- /**
- * Handle the given update event.
+
+ /**
+ * The given save-update event named a detached entity.
+ * <p/>
+ * Here, we will perform the update processing.
*
* @param event The update event to be handled.
- * @throws HibernateException
*/
- protected void entityIsDetached(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("updating detached instance");
-
-
- if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
+ protected void entityIsDetached(SaveOrUpdateEvent event) {
+
+ log.trace( "updating detached instance" );
+
+
+ if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
//TODO: assertion only, could be optimized away
- throw new AssertionFailure("entity was persistent");
+ throw new AssertionFailure( "entity was persistent" );
}
-
+
Object entity = event.getEntity();
EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), entity );
- event.setRequestedId( getUpdateId( entity, persister, event.getRequestedId(), event.getSession().getEntityMode() ) );
-
- performUpdate(event, entity, persister);
+ event.setRequestedId(
+ getUpdateId(
+ entity, persister, event.getRequestedId(), event.getSession().getEntityMode()
+ )
+ );
+ performUpdate( event, entity, persister );
+
}
-
- protected Serializable getUpdateId(Object entity, EntityPersister persister, Serializable requestedId, EntityMode entityMode)
- throws HibernateException {
+
+ /**
+ * Determine the id to use for updating.
+ *
+ * @param entity The entity.
+ * @param persister The entity persister
+ * @param requestedId The requested identifier
+ * @param entityMode The entity mode.
+ *
+ * @return The id.
+ *
+ * @throws TransientObjectException If the entity is considered transient.
+ */
+ protected Serializable getUpdateId(
+ Object entity,
+ EntityPersister persister,
+ Serializable requestedId,
+ EntityMode entityMode) {
// use the id assigned to the instance
- Serializable id = persister.getIdentifier(entity, entityMode);
- if ( id==null ) {
+ Serializable id = persister.getIdentifier( entity, entityMode );
+ if ( id == null ) {
// assume this is a newly instantiated transient object
// which should be saved rather than updated
throw new TransientObjectException(
"The given object has a null identifier: " +
- persister.getEntityName()
- );
+ persister.getEntityName()
+ );
}
else {
return id;
}
-
+
}
- protected void performUpdate(SaveOrUpdateEvent event, Object entity, EntityPersister persister)
- throws HibernateException {
-
+ protected void performUpdate(
+ SaveOrUpdateEvent event,
+ Object entity,
+ EntityPersister persister) throws HibernateException {
+
if ( !persister.isMutable() ) {
log.trace( "immutable instance passed to doUpdate(), locking" );
reassociate( event, entity, event.getRequestedId(), persister );
@@ -246,27 +269,29 @@
else {
if ( log.isTraceEnabled() ) {
- log.trace(
- "updating " +
- MessageHelper.infoString( persister, event.getRequestedId(), event.getSession().getFactory() )
- );
+ log.trace(
+ "updating " +
+ MessageHelper.infoString(
+ persister, event.getRequestedId(), event.getSession().getFactory()
+ )
+ );
}
-
+
final EventSource source = event.getSession();
-
+
EntityKey key = new EntityKey( event.getRequestedId(), persister, source.getEntityMode() );
-
+
source.getPersistenceContext().checkUniqueness( key, entity );
-
+
if ( invokeUpdateLifecycle( entity, persister, source ) ) {
reassociate( event, event.getObject(), event.getRequestedId(), persister );
return;
}
-
+
// this is a transient object with existing persistent state not loaded by the session
-
- new OnUpdateVisitor( source, event.getRequestedId() ).process( entity, persister );
-
+
+ new OnUpdateVisitor( source, event.getRequestedId(), entity ).process( entity, persister );
+
//TODO: put this stuff back in to read snapshot from
// the second-level cache (needs some extra work)
/*Object[] cachedState = null;
@@ -288,28 +313,28 @@
LockMode.NONE,
true,
persister,
- false,
+ false,
true //assume true, since we don't really know, and it doesn't matter
+ );
+
+ persister.afterReassociate( entity, source );
+
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ "updating " +
+ MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() )
);
-
- persister.afterReassociate(entity, source);
-
- if ( log.isTraceEnabled() ) {
- log.trace(
- "updating " +
- MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() )
- );
}
-
- cascadeOnUpdate(event, persister, entity);
-
+
+ cascadeOnUpdate( event, persister, entity );
+
}
}
protected boolean invokeUpdateLifecycle(Object entity, EntityPersister persister, EventSource source) {
if ( persister.implementsLifecycle( source.getEntityMode() ) ) {
log.debug( "calling onUpdate()" );
- if ( ( ( Lifecycle ) entity ).onUpdate(source) ) {
+ if ( ( ( Lifecycle ) entity ).onUpdate( source ) ) {
log.debug( "update vetoed by onUpdate()" );
return true;
}
@@ -329,8 +354,8 @@
EventSource source = event.getSession();
source.getPersistenceContext().incrementCascadeLevel();
try {
- new Cascade(CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source)
- .cascade(persister, entity);
+ new Cascade( CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source )
+ .cascade( persister, entity );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -14,60 +14,55 @@
* When a transient entity is passed to lock(), we must inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
- * existing snapshot
+ * existing snapshot
* 3. throw an exception for each "new" collection
*
* @author Gavin King
*/
public class OnLockVisitor extends ReattachVisitor {
- public OnLockVisitor(EventSource session, Serializable key) {
- super(session, key);
+ public OnLockVisitor(EventSource session, Serializable key, Object owner) {
+ super( session, key, owner );
}
- Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
+ Object processCollection(Object collection, CollectionType type) throws HibernateException {
SessionImplementor session = getSession();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
- if (collection==null) {
+ if ( collection == null ) {
//do nothing
}
else if ( collection instanceof PersistentCollection ) {
- PersistentCollection persistentCollection = (PersistentCollection) collection;
-
- if ( persistentCollection.setCurrentSession(session) ) {
-
- if ( isOwnerUnchanged( persistentCollection, persister, getKey() ) ) {
+ PersistentCollection persistentCollection = ( PersistentCollection ) collection;
+ if ( persistentCollection.setCurrentSession( session ) ) {
+ if ( isOwnerUnchanged( persistentCollection, persister, extractCollectionKeyFromOwner( persister ) ) ) {
// a "detached" collection that originally belonged to the same entity
if ( persistentCollection.isDirty() ) {
- throw new HibernateException("reassociated object has dirty collection");
+ throw new HibernateException( "reassociated object has dirty collection" );
}
- reattachCollection(persistentCollection, type);
+ reattachCollection( persistentCollection, type );
}
else {
// a "detached" collection that belonged to a different entity
- throw new HibernateException("reassociated object has dirty collection reference");
+ throw new HibernateException( "reassociated object has dirty collection reference" );
}
-
}
else {
// a collection loaded in the current session
// can not possibly be the collection belonging
// to the entity passed to update()
- throw new HibernateException("reassociated object has dirty collection reference");
+ throw new HibernateException( "reassociated object has dirty collection reference" );
}
-
}
else {
// brand new collection
//TODO: or an array!! we can't lock objects with arrays now??
- throw new HibernateException("reassociated object has dirty collection reference (or an array)");
+ throw new HibernateException( "reassociated object has dirty collection reference (or an array)" );
}
return null;
}
-
+
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -10,40 +10,43 @@
import org.hibernate.type.CollectionType;
/**
- * When an entity is passed to replicate(), and there is an existing row, we must
+ * When an entity is passed to replicate(), and there is an existing row, we must
* inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
- * existing snapshot
+ * existing snapshot
* 3. execute a collection removal (SQL DELETE) for each null collection property
- * or "new" collection
+ * or "new" collection
*
* @author Gavin King
*/
public class OnReplicateVisitor extends ReattachVisitor {
-
+
private boolean isUpdate;
-
- OnReplicateVisitor(EventSource session, Serializable key, boolean isUpdate) {
- super(session, key);
+
+ OnReplicateVisitor(EventSource session, Serializable key, Object owner, boolean isUpdate) {
+ super( session, key, owner );
this.isUpdate = isUpdate;
}
Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
-
- if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+ throws HibernateException {
+ if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+ return null;
+ }
+
EventSource session = getSession();
- Serializable key = getKey();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
- if (isUpdate) removeCollection(persister, key, session);
- if ( collection!=null && (collection instanceof PersistentCollection) ) {
- PersistentCollection wrapper = (PersistentCollection) collection;
- wrapper.setCurrentSession(session);
+ if ( isUpdate ) {
+ removeCollection( persister, extractCollectionKeyFromOwner( persister ), session );
+ }
+ if ( collection != null && ( collection instanceof PersistentCollection ) ) {
+ PersistentCollection wrapper = ( PersistentCollection ) collection;
+ wrapper.setCurrentSession( session );
if ( wrapper.wasInitialized() ) {
- session.getPersistenceContext().addNewCollection(persister, wrapper);
+ session.getPersistenceContext().addNewCollection( persister, wrapper );
}
else {
reattachCollection( wrapper, type );
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -21,51 +21,49 @@
*/
public class OnUpdateVisitor extends ReattachVisitor {
- OnUpdateVisitor(EventSource session, Serializable key) {
- super(session, key);
+ OnUpdateVisitor(EventSource session, Serializable key, Object owner) {
+ super( session, key, owner );
}
- Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
+ /**
+ * {@inheritDoc}
+ */
+ Object processCollection(Object collection, CollectionType type) throws HibernateException {
- if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+ if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+ return null;
+ }
EventSource session = getSession();
- Serializable key = getKey();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
+ final Serializable collectionKey = extractCollectionKeyFromOwner( persister );
if ( collection!=null && (collection instanceof PersistentCollection) ) {
PersistentCollection wrapper = (PersistentCollection) collection;
-
if ( wrapper.setCurrentSession(session) ) {
//a "detached" collection!
-
- if ( !isOwnerUnchanged(wrapper, persister, key) ) {
+ if ( !isOwnerUnchanged( wrapper, persister, collectionKey ) ) {
// if the collection belonged to a different entity,
// clean up the existing state of the collection
- removeCollection(persister, key, session);
+ removeCollection( persister, collectionKey, session );
}
-
reattachCollection(wrapper, type);
}
else {
// a collection loaded in the current session
// can not possibly be the collection belonging
// to the entity passed to update()
- removeCollection(persister, key, session);
+ removeCollection(persister, collectionKey, session);
}
-
}
else {
// null or brand new collection
// this will also (inefficiently) handle arrays, which have
// no snapshot, so we can't do any better
- removeCollection(persister, key, session);
- //processArrayOrNewCollection(collection, type);
+ removeCollection(persister, collectionKey, session);
}
return null;
-
}
}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -14,34 +14,51 @@
import org.hibernate.type.Type;
/**
- * Abstract superclass of visitors that reattach collections
+ * Abstract superclass of visitors that reattach collections.
+ *
* @author Gavin King
*/
public abstract class ReattachVisitor extends ProxyVisitor {
- private static final Log log = LogFactory.getLog(ReattachVisitor.class);
+ private static final Log log = LogFactory.getLog( ReattachVisitor.class );
- private final Serializable key;
+ private final Serializable ownerIdentifier;
+ private final Object owner;
- final Serializable getKey() {
- return key;
+ public ReattachVisitor(EventSource session, Serializable ownerIdentifier, Object owner) {
+ super( session );
+ this.ownerIdentifier = ownerIdentifier;
+ this.owner = owner;
}
- public ReattachVisitor(EventSource session, Serializable key) {
- super(session);
- this.key=key;
+ /**
+ * Retrieve the identifier of the entity being visited.
+ *
+ * @return The entity's identifier.
+ */
+ final Serializable getOwnerIdentifier() {
+ return ownerIdentifier;
}
- Object processComponent(Object component, AbstractComponentType componentType)
- throws HibernateException {
+ /**
+ * Retrieve the entity being visited.
+ *
+ * @return The entity.
+ */
+ final Object getOwner() {
+ return owner;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ Object processComponent(Object component, AbstractComponentType componentType) throws HibernateException {
Type[] types = componentType.getSubtypes();
- if (component==null) {
+ if ( component == null ) {
processValues( new Object[types.length], types );
}
else {
- super.processComponent(component, componentType);
- //processValues( componentType.getPropertyValues( component, getSession() ), types );
+ super.processComponent( component, componentType );
}
return null;
@@ -51,23 +68,35 @@
* Schedules a collection for deletion.
*
* @param role The persister representing the collection to be removed.
- * @param id The id of the entity containing the collection to be removed.
+ * @param collectionKey The collection key (differs from owner-id in the case of property-refs).
+ * @param source The session from which the request originated.
* @throws HibernateException
*/
- public void removeCollection(CollectionPersister role, Serializable id, EventSource source)
- throws HibernateException {
- if ( log.isTraceEnabled() )
+ void removeCollection(CollectionPersister role, Serializable collectionKey, EventSource source) throws HibernateException {
+ if ( log.isTraceEnabled() ) {
log.trace(
"collection dereferenced while transient " +
- MessageHelper.collectionInfoString( role, id, source.getFactory() )
+ MessageHelper.collectionInfoString( role, ownerIdentifier, source.getFactory() )
);
- /*if ( role.hasOrphanDelete() ) {
- throw new HibernateException(
- "You may not dereference a collection with cascade=\"all-delete-orphan\": " +
- MessageHelper.infoString(role, id)
- );
- }*/
- source.getActionQueue().addAction( new CollectionRemoveAction( null, role, id, false, source ) );
+ }
+ source.getActionQueue().addAction( new CollectionRemoveAction( null, role, collectionKey, false, source ) );
}
+ /**
+ * This version is slightly different in that here we need to assume that
+ * the owner is not yet associated with the session, and thus we cannot
+ * rely on the owner's EntityEntry snapshot...
+ *
+ * @param role The persister for the collection role being processed.
+ * @return
+ */
+ final Serializable extractCollectionKeyFromOwner(CollectionPersister role) {
+ if ( role.getCollectionType().useLHSPrimaryKey() ) {
+ return ownerIdentifier;
+ }
+ else {
+ return ( Serializable ) role.getOwnerEntityPersister().getPropertyValue( owner, role.getCollectionType().getLHSPropertyName(), getSession().getEntityMode() );
+ }
+
+ }
}
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml 2006-12-07 21:53:41 UTC (rev 10949)
@@ -31,6 +31,10 @@
<key column="userId" property-ref="userId"/>
<one-to-many class="Account"/>
</set>
+ <bag name="systems" table="USER_SYSTEM" lazy="true" inverse="false" cascade="all">
+ <key column="USER_ID" property-ref="userId" />
+ <element type="string" column="SYSTEM" />
+ </bag>
</class>
<class name="Address" table="PROPREF_ADDR">
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -3,6 +3,8 @@
import java.util.HashSet;
import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
/**
* @author gavin
@@ -13,6 +15,8 @@
private Address address;
private String userId;
private Set accounts = new HashSet();
+ private List systems = new ArrayList();
+
/**
* @return Returns the userId.
*/
@@ -73,4 +77,12 @@
public void setAccounts(Set accounts) {
this.accounts = accounts;
}
+
+ public List getSystems() {
+ return systems;
+ }
+
+ public void setSystems(List systems) {
+ this.systems = systems;
+ }
}
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java 2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java 2006-12-07 21:53:41 UTC (rev 10949)
@@ -22,7 +22,7 @@
* @author Gavin King
*/
public class PropertyRefTest extends TestCase {
-
+
public PropertyRefTest(String str) {
super(str);
}
@@ -39,7 +39,44 @@
cfg.setProperty(Environment.DEFAULT_BATCH_FETCH_SIZE, "1");
cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
}
-
+
+ public String getCacheConcurrencyStrategy() {
+ return null;
+ }
+
+ public void testNonLazyBagKeyPropertyRef() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Person p = new Person();
+ p.setName( "Steve" );
+ p.setUserId( "steve" );
+ p.getSystems().add( "QA" );
+ p.getSystems().add( "R&D" );
+ s.persist( p );
+ t.commit();
+ s.close();
+
+ s = openSession();
+ t = s.beginTransaction();
+ s.createQuery( "from Person" ).list();
+ s.clear();
+ s.createSQLQuery( "select {p.*} from PROPREF_PERS {p}" )
+ .addEntity( "p", Person.class.getName() )
+ .list();
+ t.commit();
+ s.close();
+
+ s = openSession();
+ t = s.beginTransaction();
+ List results = s.createQuery( "from Person" ).list();
+ Iterator itr = results.iterator();
+ while ( itr.hasNext() ) {
+ s.delete( itr.next() );
+ }
+ t.commit();
+ s.close();
+ }
+
public void testManyToManyPropertyRef() {
// prepare some test data relating to the Group->Person many-to-many association
Session s = openSession();
@@ -78,7 +115,7 @@
t.commit();
s.close();
}
-
+
public void testOneToOnePropertyRef() {
Session s = openSession();
Transaction t = s.beginTransaction();
@@ -102,7 +139,7 @@
s.save(act);
s.flush();
s.clear();
-
+
p = (Person) s.get( Person.class, p.getId() ); //get address reference by outer join
p2 = (Person) s.get( Person.class, p2.getId() ); //get null address reference by outer join
assertNull( p2.getAddress() );
@@ -111,13 +148,13 @@
assertEquals( l.size(), 2 );
assertTrue( l.contains(p) && l.contains(p2) );
s.clear();
-
+
l = s.createQuery("from Person p order by p.name").list(); //get address references by sequential selects
assertEquals( l.size(), 2 );
assertNull( ( (Person) l.get(0) ).getAddress() );
assertNotNull( ( (Person) l.get(1) ).getAddress() );
s.clear();
-
+
l = s.createQuery("from Person p left join fetch p.address a order by a.country").list(); //get em by outer join
assertEquals( l.size(), 2 );
if ( ( (Person) l.get(0) ).getName().equals("Max") ) {
@@ -129,7 +166,7 @@
assertNotNull( ( (Person) l.get(0) ).getAddress() );
}
s.clear();
-
+
l = s.createQuery("from Person p left join p.accounts a").list();
for ( int i=0; i<2; i++ ) {
Object[] row = (Object[]) l.get(i);
@@ -152,16 +189,16 @@
assertTrue( Hibernate.isInitialized(acc.getUser()) );
assertNotNull(acc.getUser());
assertTrue( acc.getUser().getAccounts().contains(acc) );
-
+
s.createQuery("delete from Address").executeUpdate();
s.createQuery("delete from Account").executeUpdate(); // to not break constraint violation between Person and Account
s.createQuery("delete from Person").executeUpdate();
-
+
t.commit();
s.close();
}
-
+
public void testJoinFetchPropertyRef() {
Session s = openSession();
Transaction t = s.beginTransaction();
@@ -181,7 +218,7 @@
getSessions().getStatistics().clear();
p = (Person) s.get( Person.class, p.getId() ); //get address reference by outer join
-
+
assertTrue( Hibernate.isInitialized( p.getAddress() ) );
assertNotNull( p.getAddress() );
assertEquals( getSessions().getStatistics().getPrepareStatementCount(), 1 );
@@ -194,7 +231,7 @@
p = (Person) s.createCriteria(Person.class)
.setFetchMode("address", FetchMode.SELECT)
.uniqueResult(); //get address reference by select
-
+
assertTrue( Hibernate.isInitialized( p.getAddress() ) );
assertNotNull( p.getAddress() );
assertEquals( getSessions().getStatistics().getPrepareStatementCount(), 2 );
@@ -202,30 +239,30 @@
s.createQuery("delete from Address").executeUpdate();
s.createQuery("delete from Person").executeUpdate();
-
+
t.commit();
s.close();
}
public void testForeignKeyCreation() {
PersistentClass classMapping = getCfg().getClassMapping("org.hibernate.test.propertyref.basic.Account");
-
+
Iterator foreignKeyIterator = classMapping.getTable().getForeignKeyIterator();
boolean found = false;
while ( foreignKeyIterator.hasNext() ) {
ForeignKey element = (ForeignKey) foreignKeyIterator.next();
if(element.getReferencedEntityName().equals(Person.class.getName() ) ) {
-
+
if(!element.isReferenceToPrimaryKey() ) {
List referencedColumns = element.getReferencedColumns();
Column column = (Column) referencedColumns.get(0);
if(column.getName().equals("person_userid") ) {
found = true; // extend test to include the columns
- }
+ }
}
}
}
-
+
assertTrue("Property ref foreign key not found",found);
}
}
17 years, 4 months
Hibernate SVN: r10948 - in trunk/Hibernate3: src/org/hibernate/event/def test/org/hibernate/test/propertyref/basic
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 16:53:10 -0500 (Thu, 07 Dec 2006)
New Revision: 10948
Modified:
trunk/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
trunk/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
trunk/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
trunk/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
trunk/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
trunk/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
trunk/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
trunk/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
Log:
HHH-2291 - reattachment of collections with a property-ref key;
code and javadoc cleanup
Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -5,7 +5,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
import org.hibernate.LockMode;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.EntityKey;
@@ -25,7 +25,7 @@
*/
public class AbstractReassociateEventListener implements Serializable {
- private static final Log log = LogFactory.getLog(AbstractReassociateEventListener.class);
+ private static final Log log = LogFactory.getLog( AbstractReassociateEventListener.class );
/**
* Associates a given entity (either transient or associated with another session) to
@@ -35,52 +35,53 @@
* @param object The entity to be associated
* @param id The id of the entity.
* @param persister The entity's persister instance.
+ *
* @return An EntityEntry representing the entity within this session.
- * @throws HibernateException
*/
- protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister)
- throws HibernateException {
-
- if ( log.isTraceEnabled() ) log.trace(
- "reassociating transient instance: " +
- MessageHelper.infoString( persister, id, event.getSession().getFactory() )
+ protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister) {
+
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ "reassociating transient instance: " +
+ MessageHelper.infoString( persister, id, event.getSession().getFactory() )
);
-
+ }
+
EventSource source = event.getSession();
EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
-
- source.getPersistenceContext().checkUniqueness(key, object);
-
+
+ source.getPersistenceContext().checkUniqueness( key, object );
+
//get a snapshot
Object[] values = persister.getPropertyValues( object, source.getEntityMode() );
- TypeFactory.deepCopy(
- values,
- persister.getPropertyTypes(),
- persister.getPropertyUpdateability(),
- values,
- source
- );
- Object version = Versioning.getVersion(values, persister);
-
+ TypeFactory.deepCopy(
+ values,
+ persister.getPropertyTypes(),
+ persister.getPropertyUpdateability(),
+ values,
+ source
+ );
+ Object version = Versioning.getVersion( values, persister );
+
EntityEntry newEntry = source.getPersistenceContext().addEntity(
- object,
- Status.MANAGED,
- values,
- key,
- version,
- LockMode.NONE,
- true,
- persister,
- false,
+ object,
+ Status.MANAGED,
+ values,
+ key,
+ version,
+ LockMode.NONE,
+ true,
+ persister,
+ false,
true //will be ignored, using the existing Entry instead
- );
-
- new OnLockVisitor( source, id ).process( object, persister );
-
+ );
+
+ new OnLockVisitor( source, id, object ).process( object, persister );
+
persister.afterReassociate( object, source );
-
+
return newEntry;
-
+
}
}
Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -6,7 +6,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.action.EntityIdentityInsertAction;
@@ -44,60 +44,59 @@
protected static final int DETACHED = 2;
protected static final int DELETED = 3;
- private static final Log log = LogFactory.getLog(AbstractSaveEventListener.class);
+ private static final Log log = LogFactory.getLog( AbstractSaveEventListener.class );
/**
* Prepares the save call using the given requested id.
+ *
* @param entity The entity to be saved.
* @param requestedId The id to which to associate the entity.
+ * @param entityName The name of the entity being saved.
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
+ *
* @return The id used to save the entity.
- * @throws HibernateException
*/
protected Serializable saveWithRequestedId(
Object entity,
Serializable requestedId,
String entityName,
Object anything,
- EventSource source)
- throws HibernateException {
+ EventSource source) {
return performSave(
entity,
requestedId,
- source.getEntityPersister(entityName, entity),
+ source.getEntityPersister( entityName, entity ),
false,
anything,
source,
- true
- );
+ true
+ );
}
/**
* Prepares the save call using a newly generated id.
+ *
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
-
- EntityPersister persister = source.getEntityPersister(entityName, entity);
-
- Serializable generatedId = persister.getIdentifierGenerator()
- .generate( source, entity );
-
+ boolean requiresImmediateIdAccess) {
+ EntityPersister persister = source.getEntityPersister( entityName, entity );
+ Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() );
}
@@ -108,16 +107,17 @@
return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess );
}
else {
-
+
if ( log.isDebugEnabled() ) {
log.debug(
- "generated identifier: " +
- persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ) +
- ", using strategy: " +
- persister.getIdentifierGenerator().getClass().getName() //TODO: define toString()s for generators
- );
+ "generated identifier: " +
+ persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ) +
+ ", using strategy: " +
+ persister.getIdentifierGenerator().getClass().getName()
+ //TODO: define toString()s for generators
+ );
}
-
+
return performSave( entity, generatedId, persister, false, anything, source, true );
}
}
@@ -125,18 +125,20 @@
/**
* Ppepares the save call by checking the session caches for a pre-existing
* entity and performing any lifecycle callbacks.
+ *
* @param entity The entity to be saved.
* @param id The id by which to save the entity.
* @param persister The entity's persister instance.
- * @param useIdentityColumn Is an identity column in use?
+ * @param useIdentityColumn Is an identity column being used?
+ * @param anything Generally cascade-specific information.
* @param source The session from which the event originated.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable performSave(
Object entity,
@@ -145,55 +147,54 @@
boolean useIdentityColumn,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
+ boolean requiresImmediateIdAccess) {
if ( log.isTraceEnabled() ) {
- log.trace(
- "saving " +
- MessageHelper.infoString( persister, id, source.getFactory() )
- );
+ log.trace(
+ "saving " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
-
+
EntityKey key;
if ( !useIdentityColumn ) {
key = new EntityKey( id, persister, source.getEntityMode() );
- Object old = source.getPersistenceContext().getEntity(key);
- if (old != null) {
- if ( source.getPersistenceContext().getEntry(old).getStatus() == Status.DELETED ) {
- source.forceFlush( source.getPersistenceContext().getEntry(old) );
+ Object old = source.getPersistenceContext().getEntity( key );
+ if ( old != null ) {
+ if ( source.getPersistenceContext().getEntry( old ).getStatus() == Status.DELETED ) {
+ source.forceFlush( source.getPersistenceContext().getEntry( old ) );
}
else {
throw new NonUniqueObjectException( id, persister.getEntityName() );
}
}
- persister.setIdentifier(entity, id, source.getEntityMode());
+ persister.setIdentifier( entity, id, source.getEntityMode() );
}
else {
key = null;
}
-
- if ( invokeSaveLifecycle(entity, persister, source) ) {
+
+ if ( invokeSaveLifecycle( entity, persister, source ) ) {
return id; //EARLY EXIT
}
return performSaveOrReplicate(
- entity,
- key,
- persister,
- useIdentityColumn,
- anything,
+ entity,
+ key,
+ persister,
+ useIdentityColumn,
+ anything,
source,
- requiresImmediateIdAccess
- );
+ requiresImmediateIdAccess
+ );
}
-
+
protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) {
// Sub-insertions should occur before containing insertion so
// Try to do the callback now
if ( persister.implementsLifecycle( source.getEntityMode() ) ) {
log.debug( "calling onSave()" );
- if ( ( (Lifecycle) entity ).onSave(source) ) {
+ if ( ( ( Lifecycle ) entity ).onSave( source ) ) {
log.debug( "insertion vetoed by onSave()" );
return true;
}
@@ -203,21 +204,25 @@
protected void validate(Object entity, EntityPersister persister, EventSource source) {
if ( persister.implementsValidatable( source.getEntityMode() ) ) {
- ( ( Validatable ) entity ).validate();
- }
+ ( ( Validatable ) entity ).validate();
+ }
}
/**
* Performs all the actual work needed to save an entity (well to get the save moved to
* the execution queue).
+ *
* @param entity The entity to be saved
* @param key The id to be used for saving the entity (or null, in the case of identity columns)
* @param persister The entity's persister instance.
* @param useIdentityColumn Should an identity column be used for id generation?
+ * @param anything Generally cascade-specific information.
* @param source The session which is the source of the current event.
+ * @param requiresImmediateIdAccess Is access to the identifier required immediately
+ * after the completion of the save? persist(), for example, does not require this...
+ *
* @return The id used to save the entity; may be null depending on the
- * type of id generator used and the requiresImmediateIdAccess value
- * @throws HibernateException
+ * type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable performSaveOrReplicate(
Object entity,
@@ -226,18 +231,17 @@
boolean useIdentityColumn,
Object anything,
EventSource source,
- boolean requiresImmediateIdAccess)
- throws HibernateException {
-
+ boolean requiresImmediateIdAccess) {
+
validate( entity, persister, source );
- Serializable id = key==null ? null : key.getIdentifier();
+ Serializable id = key == null ? null : key.getIdentifier();
boolean inTxn = source.getJDBCContext().isTransactionInProgress();
boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
if ( useIdentityColumn && !shouldDelayIdentityInserts ) {
- log.trace("executing insertions");
+ log.trace( "executing insertions" );
source.getActionQueue().executeInserts();
}
@@ -253,46 +257,50 @@
null,
LockMode.WRITE,
useIdentityColumn,
- persister,
- false,
+ persister,
+ false,
false
- );
+ );
- cascadeBeforeSave(source, persister, entity, anything);
+ cascadeBeforeSave( source, persister, entity, anything );
- Object[] values = persister.getPropertyValuesToInsert(entity, getMergeMap(anything), source);
+ Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source );
Type[] types = persister.getPropertyTypes();
- boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source);
+ boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
if ( persister.hasCollections() ) {
- substitute = substitute || visitCollectionsBeforeSave(id, values, types, source);
+ substitute = substitute || visitCollectionsBeforeSave( entity, id, values, types, source );
}
- if (substitute) persister.setPropertyValues( entity, values, source.getEntityMode() );
+ if ( substitute ) {
+ persister.setPropertyValues( entity, values, source.getEntityMode() );
+ }
- TypeFactory.deepCopy(
- values,
- types,
- persister.getPropertyUpdateability(),
- values,
+ TypeFactory.deepCopy(
+ values,
+ types,
+ persister.getPropertyUpdateability(),
+ values,
source
+ );
+
+ new ForeignKeys.Nullifier( entity, false, useIdentityColumn, source )
+ .nullifyTransientReferences( values, types );
+ new Nullability( source ).checkNullability( values, persister, false );
+
+ if ( useIdentityColumn ) {
+ EntityIdentityInsertAction insert = new EntityIdentityInsertAction(
+ values, entity, persister, source, shouldDelayIdentityInserts
);
-
- new ForeignKeys.Nullifier(entity, false, useIdentityColumn, source)
- .nullifyTransientReferences(values, types);
- new Nullability(source).checkNullability( values, persister, false );
-
- if ( useIdentityColumn ) {
- EntityIdentityInsertAction insert = new EntityIdentityInsertAction( values, entity, persister, source, shouldDelayIdentityInserts );
- if ( ! shouldDelayIdentityInserts ) {
+ if ( !shouldDelayIdentityInserts ) {
log.debug( "executing identity-insert immediately" );
- source.getActionQueue().execute(insert);
+ source.getActionQueue().execute( insert );
id = insert.getGeneratedId();
//now done in EntityIdentityInsertAction
//persister.setIdentifier( entity, id, source.getEntityMode() );
key = new EntityKey( id, persister, source.getEntityMode() );
- source.getPersistenceContext().checkUniqueness(key, entity);
+ source.getPersistenceContext().checkUniqueness( key, entity );
//source.getBatcher().executeBatch(); //found another way to ensure that all batched joined inserts have been executed
}
else {
@@ -302,7 +310,7 @@
}
}
- Object version = Versioning.getVersion(values, persister);
+ Object version = Versioning.getVersion( values, persister );
source.getPersistenceContext().addEntity(
entity,
Status.MANAGED,
@@ -312,18 +320,18 @@
LockMode.WRITE,
useIdentityColumn,
persister,
- isVersionIncrementDisabled(),
+ isVersionIncrementDisabled(),
false
- );
+ );
//source.getPersistenceContext().removeNonExist( new EntityKey( id, persister, source.getEntityMode() ) );
if ( !useIdentityColumn ) {
- source.getActionQueue().addAction(
- new EntityInsertAction(id, values, entity, version, persister, source)
- );
+ source.getActionQueue().addAction(
+ new EntityInsertAction( id, values, entity, version, persister, source )
+ );
}
- cascadeAfterSave(source, persister, entity, anything);
+ cascadeAfterSave( source, persister, entity, anything );
markInterceptorDirty( entity, persister, source );
@@ -333,7 +341,7 @@
private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.injectFieldInterceptor(
- entity,
+ entity,
persister.getEntityName(),
null,
source
@@ -341,44 +349,55 @@
interceptor.dirty();
}
}
-
+
protected Map getMergeMap(Object anything) {
return null;
}
-
+
/**
* After the save, will te version number be incremented
* if the instance is modified?
+ *
+ * @return True if the version will be incremented on an entity change after save;
+ * false otherwise.
*/
protected boolean isVersionIncrementDisabled() {
return false;
}
-
- protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
- WrapVisitor visitor = new WrapVisitor(source);
+
+ protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
+ WrapVisitor visitor = new WrapVisitor( source );
// substitutes into values by side-effect
- visitor.processEntityPropertyValues(values, types);
+ visitor.processEntityPropertyValues( values, types );
return visitor.isSubstitutionRequired();
}
-
+
/**
* Perform any property value substitution that is necessary
* (interceptor callback, version initialization...)
+ *
+ * @param entity The entity
+ * @param id The entity identifier
+ * @param values The snapshot entity state
+ * @param persister The entity persister
+ * @param source The originating session
+ *
+ * @return True if the snapshot state changed such that
+ * reinjection of the values into the entity is required.
*/
protected boolean substituteValuesIfNecessary(
- Object entity,
- Serializable id,
- Object[] values,
+ Object entity,
+ Serializable id,
+ Object[] values,
EntityPersister persister,
- SessionImplementor source
- ) {
+ SessionImplementor source) {
boolean substitute = source.getInterceptor().onSave(
entity,
id,
values,
persister.getPropertyNames(),
persister.getPropertyTypes()
- );
+ );
//keep the existing version number in the case of replicate!
if ( persister.isVersioned() ) {
@@ -386,7 +405,7 @@
values,
persister.getVersionProperty(),
persister.getVersionType(),
- source
+ source
) || substitute;
}
return substitute;
@@ -394,23 +413,23 @@
/**
* Handles the calls needed to perform pre-save cascades for the given entity.
+ *
* @param source The session from whcih the save event originated.
* @param persister The entity's persister instance.
* @param entity The entity to be saved.
- * @throws HibernateException
+ * @param anything Generally cascade-specific data
*/
protected void cascadeBeforeSave(
EventSource source,
EntityPersister persister,
Object entity,
- Object anything)
- throws HibernateException {
+ Object anything) {
// cascade-save to many-to-one BEFORE the parent is saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), Cascade.BEFORE_INSERT_AFTER_DELETE, source )
- .cascade(persister, entity, anything);
+ .cascade( persister, entity, anything );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
@@ -419,96 +438,105 @@
/**
* Handles to calls needed to perform post-save cascades.
+ *
* @param source The session from which the event originated.
* @param persister The entity's persister instance.
* @param entity The entity beng saved.
- * @throws HibernateException
+ * @param anything Generally cascade-specific data
*/
protected void cascadeAfterSave(
EventSource source,
- EntityPersister persister,
- Object entity,
- Object anything)
- throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ Object anything) {
// cascade-save to collections AFTER the collection owner was saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), Cascade.AFTER_INSERT_BEFORE_DELETE, source )
- .cascade(persister, entity, anything);
+ .cascade( persister, entity, anything );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
}
}
-
+
protected abstract CascadingAction getCascadeAction();
-
+
/**
* Determine whether the entity is persistent, detached, or transient
+ *
+ * @param entity The entity to check
+ * @param entityName The name of the entity
+ * @param entry The entity's entry in the persistence context
+ * @param source The originating session.
+ *
+ * @return The state.
*/
protected int getEntityState(
- Object entity,
- String entityName,
+ Object entity,
+ String entityName,
EntityEntry entry, //pass this as an argument only to avoid double looking
SessionImplementor source) {
- if ( entry != null ) {
- // the object is persistent as it has an entry associated with the
- // session; so check its status
+ if ( entry != null ) { // the object is persistent
+
+ //the entity is associated with the session, so check its status
if ( entry.getStatus() != Status.DELETED ) {
// do nothing for persistent instances
if ( log.isTraceEnabled() ) {
- log.trace(
- "persistent instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "persistent instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return PERSISTENT;
}
- else {
+ else {
//ie. e.status==DELETED
if ( log.isTraceEnabled() ) {
- log.trace(
- "deleted instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "deleted instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return DELETED;
}
-
+
}
- else {
- // the entity is not associated with the session, so the various
- // unsaved-value algorithms to determine whether it is transient
- // or detached
+ else { // the object is transient or detached
+
+ //the entity is not associated with the session, so
+ //try interceptor and unsaved-value
+
if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) {
if ( log.isTraceEnabled() ) {
- log.trace(
- "transient instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "transient instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return TRANSIENT;
}
else {
if ( log.isTraceEnabled() ) {
- log.trace(
- "detached instance of: " +
- getLoggableName(entityName, entity)
- );
+ log.trace(
+ "detached instance of: " +
+ getLoggableName( entityName, entity )
+ );
}
return DETACHED;
}
}
}
-
+
protected String getLoggableName(String entityName, Object entity) {
- return entityName==null ? entity.getClass().getName() : entityName;
+ return entityName == null ? entity.getClass().getName() : entityName;
}
-
+
protected Boolean getAssumedUnsaved() {
return null;
}
+
}
Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -6,6 +6,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.hibernate.CacheMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
@@ -38,17 +39,27 @@
*/
public class DefaultDeleteEventListener implements DeleteEventListener {
- private static final Log log = LogFactory.getLog(DefaultDeleteEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultDeleteEventListener.class );
- /** Handle the given delete event.
- *
- * @param event The delete event to be handled.
- * @throws HibernateException
- */
+ /**
+ * Handle the given delete event.
+ *
+ * @param event The delete event to be handled.
+ *
+ * @throws HibernateException
+ */
public void onDelete(DeleteEvent event) throws HibernateException {
onDelete( event, new IdentitySet() );
}
+ /**
+ * Handle the given delete event. This is the cascaded form.
+ *
+ * @param event The delete event.
+ * @param transientEntities The cache of entities already deleted
+ *
+ * @throws HibernateException
+ */
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException {
final EventSource source = event.getSession();
@@ -79,15 +90,15 @@
if ( id == null ) {
throw new TransientObjectException(
- "the detached instance passed to delete() had a null identifier"
+ "the detached instance passed to delete() had a null identifier"
);
}
EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
- persistenceContext.checkUniqueness(key, entity);
+ persistenceContext.checkUniqueness( key, entity );
- new OnUpdateVisitor( source, id ).process( entity, persister );
+ new OnUpdateVisitor( source, id, entity ).process( entity, persister );
version = persister.getVersion( entity, source.getEntityMode() );
@@ -102,7 +113,7 @@
persister,
false,
false
- );
+ );
}
else {
log.trace( "deleting a persistent instance" );
@@ -123,7 +134,9 @@
);
}*/
- if ( invokeDeleteLifecycle( source, entity, persister ) ) return;
+ if ( invokeDeleteLifecycle( source, entity, persister ) ) {
+ return;
+ }
deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister, transientEntities );
@@ -132,6 +145,14 @@
}
}
+ /**
+ * Called when we have recognized an attempt to delete a detached entity.
+ * <p/>
+ * This is perfectly valid in Hibernate usage; JPA, however, forbids this.
+ * Thus, this is a hook for HEM to affect this behavior.
+ *
+ * @param event The event.
+ */
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
// ok in normal Hibernate usage to delete a detached entity; JPA however
// forbids it, thus this is a hook for HEM to affect this behavior
@@ -168,19 +189,31 @@
cascadeAfterDelete( session, persister, entity, transientEntities );
}
+ /**
+ * Perform the entity deletion. Well, as with most operations, does not
+ * really perform it; just schedules an action/execution with the
+ * {@link org.hibernate.engine.ActionQueue} for execution during flush.
+ *
+ * @param session The originating session
+ * @param entity The entity to delete
+ * @param entityEntry The entity's entry in the {@link PersistenceContext}
+ * @param isCascadeDeleteEnabled Is delete cascading enabled?
+ * @param persister The entity persister.
+ * @param transientEntities A cache of already deleted entities.
+ */
protected final void deleteEntity(
- final EventSource session,
- final Object entity,
- final EntityEntry entityEntry,
- final boolean isCascadeDeleteEnabled,
- final EntityPersister persister,
- final Set transientEntities) throws HibernateException {
+ final EventSource session,
+ final Object entity,
+ final EntityEntry entityEntry,
+ final boolean isCascadeDeleteEnabled,
+ final EntityPersister persister,
+ final Set transientEntities) {
if ( log.isTraceEnabled() ) {
log.trace(
"deleting " +
- MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
- );
+ MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
+ );
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
@@ -196,7 +229,7 @@
}
final Object[] deletedState = createDeletedState( persister, currentState, session );
- entityEntry.setDeletedState(deletedState);
+ entityEntry.setDeletedState( deletedState );
session.getInterceptor().onDelete(
entity,
@@ -207,15 +240,15 @@
);
// before any callbacks, etc, so subdeletions see that this deletion happened first
- persistenceContext.setEntryStatus(entityEntry, Status.DELETED);
- EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );
+ persistenceContext.setEntryStatus( entityEntry, Status.DELETED );
+ EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );
cascadeBeforeDelete( session, persister, entity, entityEntry, transientEntities );
- new ForeignKeys.Nullifier(entity, true, false, session)
+ new ForeignKeys.Nullifier( entity, true, false, session )
.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
- new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true );
- persistenceContext.getNullifiableEntityKeys().add(key);
+ new Nullability( session ).checkNullability( entityEntry.getDeletedState(), persister, true );
+ persistenceContext.getNullifiableEntityKeys().add( key );
// Ensures that containing deletions happen before sub-deletions
session.getActionQueue().addAction(
@@ -251,8 +284,8 @@
protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
if ( persister.implementsLifecycle( session.getEntityMode() ) ) {
log.debug( "calling onDelete()" );
- if ( ( (Lifecycle) entity ).onDelete(session) ) {
- log.debug("deletion vetoed by onDelete()");
+ if ( ( ( Lifecycle ) entity ).onDelete( session ) ) {
+ log.debug( "deletion vetoed by onDelete()" );
return true;
}
}
@@ -261,13 +294,13 @@
protected void cascadeBeforeDelete(
EventSource session,
- EntityPersister persister,
- Object entity,
- EntityEntry entityEntry,
- Set transientEntities) throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ EntityEntry entityEntry,
+ Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
- session.setCacheMode(CacheMode.GET);
+ session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to collections BEFORE the collection owner is deleted
@@ -276,18 +309,18 @@
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
- session.setCacheMode(cacheMode);
+ session.setCacheMode( cacheMode );
}
}
protected void cascadeAfterDelete(
EventSource session,
- EntityPersister persister,
- Object entity,
- Set transientEntities) throws HibernateException {
+ EntityPersister persister,
+ Object entity,
+ Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
- session.setCacheMode(CacheMode.GET);
+ session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to many-to-one AFTER the parent was deleted
@@ -296,7 +329,7 @@
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
- session.setCacheMode(cacheMode);
+ session.setCacheMode( cacheMode );
}
}
Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -30,44 +30,43 @@
*/
public class DefaultReplicateEventListener extends AbstractSaveEventListener implements ReplicateEventListener {
- private static final Log log = LogFactory.getLog(DefaultReplicateEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultReplicateEventListener.class );
- /**
+ /**
* Handle the given replicate event.
*
* @param event The replicate event to be handled.
- * @throws HibernateException
+ *
+ * @throws TransientObjectException An invalid attempt to replicate a transient entity.
*/
- public void onReplicate(ReplicateEvent event) throws HibernateException {
-
+ public void onReplicate(ReplicateEvent event) {
final EventSource source = event.getSession();
-
if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
- log.trace("uninitialized proxy passed to replicate()");
+ log.trace( "uninitialized proxy passed to replicate()" );
return;
}
Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );
- if ( source.getPersistenceContext().isEntryFor(entity) ) {
- log.trace("ignoring persistent instance passed to replicate()");
+ if ( source.getPersistenceContext().isEntryFor( entity ) ) {
+ log.trace( "ignoring persistent instance passed to replicate()" );
//hum ... should we cascade anyway? throw an exception? fine like it is?
return;
}
EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
-
+
// get the id from the object
/*if ( persister.isUnsaved(entity, source) ) {
throw new TransientObjectException("transient instance passed to replicate()");
}*/
Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
- if (id==null) {
- throw new TransientObjectException("instance with null id passed to replicate()");
+ if ( id == null ) {
+ throw new TransientObjectException( "instance with null id passed to replicate()" );
}
final ReplicationMode replicationMode = event.getReplicationMode();
-
+
final Object oldVersion;
if ( replicationMode == ReplicationMode.EXCEPTION ) {
//always do an INSERT, and let it fail by constraint violation
@@ -75,14 +74,16 @@
}
else {
//what is the version on the database?
- oldVersion = persister.getCurrentVersion(id, source);
+ oldVersion = persister.getCurrentVersion( id, source );
}
- if ( oldVersion!=null ) {
+ if ( oldVersion != null ) {
//existing row - do an update if appropriate
if ( log.isTraceEnabled() ) {
- log.trace( "found existing row for " +
- MessageHelper.infoString( persister, id, source.getFactory() ) );
+ log.trace(
+ "found existing row for " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
@@ -92,26 +93,28 @@
persister.getVersionType()
);
- if (canReplicate) {
+ if ( canReplicate ) {
//will result in a SQL UPDATE:
- performReplication(entity, id, oldVersion, persister, replicationMode, source);
+ performReplication( entity, id, oldVersion, persister, replicationMode, source );
}
else {
//else do nothing (don't even reassociate object!)
- log.trace("no need to replicate");
+ log.trace( "no need to replicate" );
}
-
+
//TODO: would it be better to do a refresh from db?
}
else {
// no existing row - do an insert
if ( log.isTraceEnabled() ) {
- log.trace( "no existing row, replicating new instance " +
- MessageHelper.infoString( persister, id, source.getFactory() ) );
+ log.trace(
+ "no existing row, replicating new instance " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
+ );
}
final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
- final EntityKey key = regenerate ?
+ final EntityKey key = regenerate ?
null : new EntityKey( id, persister, source.getEntityMode() );
performSaveOrReplicate(
@@ -121,77 +124,74 @@
regenerate,
replicationMode,
source,
- true
+ true
);
}
}
- protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
+ protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
//TODO: we use two visitors here, inefficient!
- OnReplicateVisitor visitor = new OnReplicateVisitor(source, id, false);
- visitor.processEntityPropertyValues(values, types);
- return super.visitCollectionsBeforeSave(id, values, types, source);
+ OnReplicateVisitor visitor = new OnReplicateVisitor( source, id, entity, false );
+ visitor.processEntityPropertyValues( values, types );
+ return super.visitCollectionsBeforeSave( entity, id, values, types, source );
}
protected boolean substituteValuesIfNecessary(
- Object entity,
- Serializable id,
- Object[] values,
+ Object entity,
+ Serializable id,
+ Object[] values,
EntityPersister persister,
- SessionImplementor source
- ) {
+ SessionImplementor source) {
return false;
}
-
+
protected boolean isVersionIncrementDisabled() {
return true;
}
-
- private final void performReplication(
+
+ private void performReplication(
Object entity,
Serializable id,
Object version,
EntityPersister persister,
ReplicationMode replicationMode,
- EventSource source)
- throws HibernateException {
+ EventSource source) throws HibernateException {
if ( log.isTraceEnabled() ) {
- log.trace(
- "replicating changes to " +
- MessageHelper.infoString( persister, id, source.getFactory() )
+ log.trace(
+ "replicating changes to " +
+ MessageHelper.infoString( persister, id, source.getFactory() )
);
}
- new OnReplicateVisitor(source, id, true).process( entity, persister );
+ new OnReplicateVisitor( source, id, entity, true ).process( entity, persister );
- source.getPersistenceContext().addEntity(
- entity,
- Status.MANAGED,
- null,
- new EntityKey( id, persister, source.getEntityMode() ),
- version,
- LockMode.NONE,
- true,
- persister,
- true,
+ source.getPersistenceContext().addEntity(
+ entity,
+ Status.MANAGED,
+ null,
+ new EntityKey( id, persister, source.getEntityMode() ),
+ version,
+ LockMode.NONE,
+ true,
+ persister,
+ true,
false
- );
+ );
cascadeAfterReplicate( entity, persister, replicationMode, source );
}
private void cascadeAfterReplicate(
- Object entity,
- EntityPersister persister,
- ReplicationMode replicationMode,
- EventSource source
- ) {
+ Object entity,
+ EntityPersister persister,
+ ReplicationMode replicationMode,
+ EventSource source) {
source.getPersistenceContext().incrementCascadeLevel();
try {
- new Cascade(CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source)
- .cascade(persister, entity, replicationMode);
+ new Cascade( CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source )
+ .cascade( persister, entity, replicationMode );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -5,6 +5,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
@@ -27,218 +28,240 @@
import org.hibernate.proxy.HibernateProxy;
/**
- * Defines the default update event listener used by hibernate for updating
- * transient entities in response to generated update events.
+ * Defines the default listener used by Hibernate for handling save-update
+ * events.
*
- * @author Steve Ebersole, Gavin King
+ * @author Steve Ebersole
+ * @author Gavin King
*/
public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener {
- private static final Log log = LogFactory.getLog(DefaultSaveOrUpdateEventListener.class);
+ private static final Log log = LogFactory.getLog( DefaultSaveOrUpdateEventListener.class );
- /**
+ /**
* Handle the given update event.
*
* @param event The update event to be handled.
- * @throws HibernateException
*/
- public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException {
-
+ public void onSaveOrUpdate(SaveOrUpdateEvent event) {
final SessionImplementor source = event.getSession();
final Object object = event.getObject();
+ final Serializable requestedId = event.getRequestedId();
- final Serializable requestedId = event.getRequestedId();
- if ( requestedId!=null ) {
- //assign the requested id to the proxy, *before*
+ if ( requestedId != null ) {
+ //assign the requested id to the proxy, *before*
//reassociating the proxy
if ( object instanceof HibernateProxy ) {
- ( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier(requestedId);
+ ( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId );
}
}
-
- if ( reassociateIfUninitializedProxy(object, source) ) {
- log.trace("reassociated uninitialized proxy");
- // an uninitialized proxy, noop, don't even need to
+
+ if ( reassociateIfUninitializedProxy( object, source ) ) {
+ log.trace( "reassociated uninitialized proxy" );
+ // an uninitialized proxy, noop, don't even need to
// return an id, since it is never a save()
}
else {
//initialize properties of the event:
- final Object entity = source.getPersistenceContext().unproxyAndReassociate(object);
- event.setEntity(entity);
- event.setEntry( source.getPersistenceContext().getEntry(entity) );
+ final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );
+ event.setEntity( entity );
+ event.setEntry( source.getPersistenceContext().getEntry( entity ) );
//return the id in the event object
- event.setResultId( performSaveOrUpdate(event) );
+ event.setResultId( performSaveOrUpdate( event ) );
}
-
+
}
-
+
protected boolean reassociateIfUninitializedProxy(Object object, SessionImplementor source) {
- return source.getPersistenceContext().reassociateIfUninitializedProxy(object);
+ return source.getPersistenceContext().reassociateIfUninitializedProxy( object );
}
-
+
protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) {
-
- // use various roles to determine if the instance is
- // transient, persistent or detached:
-
- int entityState = getEntityState(
- event.getEntity(),
- event.getEntityName(),
- event.getEntry(),
- event.getSession()
- );
-
- switch (entityState) {
- case DETACHED:
- entityIsDetached(event);
+ int entityState = getEntityState(
+ event.getEntity(),
+ event.getEntityName(),
+ event.getEntry(),
+ event.getSession()
+ );
+
+ switch ( entityState ) {
+ case DETACHED:
+ entityIsDetached( event );
return null;
case PERSISTENT:
- return entityIsPersistent(event);
+ return entityIsPersistent( event );
default: //TRANSIENT or DELETED
- return entityIsTransient(event);
+ return entityIsTransient( event );
}
-
}
-
+
protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("ignoring persistent instance");
-
+ log.trace( "ignoring persistent instance" );
+
EntityEntry entityEntry = event.getEntry();
- if ( entityEntry==null ) {
- throw new AssertionFailure("entity was transient or detached");
+ if ( entityEntry == null ) {
+ throw new AssertionFailure( "entity was transient or detached" );
}
else {
-
+
if ( entityEntry.getStatus() == Status.DELETED ) {
- throw new AssertionFailure("entity was deleted");
+ throw new AssertionFailure( "entity was deleted" );
}
-
+
final SessionFactoryImplementor factory = event.getSession().getFactory();
Serializable requestedId = event.getRequestedId();
-
+
Serializable savedId;
if ( requestedId == null ) {
savedId = entityEntry.getId();
}
else {
-
+
final boolean isEqual = !entityEntry.getPersister().getIdentifierType()
.isEqual( requestedId, entityEntry.getId(), event.getSession().getEntityMode(), factory );
-
+
if ( isEqual ) {
throw new PersistentObjectException(
"object passed to save() was already persistent: " +
- MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
- );
+ MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
+ );
}
-
+
savedId = requestedId;
-
+
}
-
+
if ( log.isTraceEnabled() ) {
- log.trace(
- "object already associated with session: " +
- MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
- );
+ log.trace(
+ "object already associated with session: " +
+ MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
+ );
}
-
+
return savedId;
-
+
}
}
-
- /**
- * Handle the given save event.
+
+ /**
+ * The given save-update event named a transient entity.
+ * <p/>
+ * Here, we will perform the save processing.
*
* @param event The save event to be handled.
- * @throws HibernateException
+ *
+ * @return The entity's identifier after saving.
*/
- protected Serializable entityIsTransient(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("saving transient instance");
+ protected Serializable entityIsTransient(SaveOrUpdateEvent event) {
- final EventSource source = event.getSession();
+ log.trace( "saving transient instance" );
+ final EventSource source = event.getSession();
+
EntityEntry entityEntry = event.getEntry();
if ( entityEntry != null ) {
if ( entityEntry.getStatus() == Status.DELETED ) {
- source.forceFlush(entityEntry);
+ source.forceFlush( entityEntry );
}
else {
- throw new AssertionFailure("entity was persistent");
+ throw new AssertionFailure( "entity was persistent" );
}
}
-
- Serializable id = saveWithGeneratedOrRequestedId(event);
+ Serializable id = saveWithGeneratedOrRequestedId( event );
+
source.getPersistenceContext().reassociateProxy( event.getObject(), id );
-
+
return id;
}
-
+
/**
* Save the transient instance, assigning the right identifier
+ *
+ * @param event The initiating event.
+ *
+ * @return The entity's identifier value after saving.
*/
protected Serializable saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) {
return saveWithGeneratedId(
- event.getEntity(),
- event.getEntityName(),
- null,
+ event.getEntity(),
+ event.getEntityName(),
+ null,
event.getSession(),
- true
+ true
);
}
-
- /**
- * Handle the given update event.
+
+ /**
+ * The given save-update event named a detached entity.
+ * <p/>
+ * Here, we will perform the update processing.
*
* @param event The update event to be handled.
- * @throws HibernateException
*/
- protected void entityIsDetached(SaveOrUpdateEvent event) throws HibernateException {
-
- log.trace("updating detached instance");
-
-
- if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
+ protected void entityIsDetached(SaveOrUpdateEvent event) {
+
+ log.trace( "updating detached instance" );
+
+
+ if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
//TODO: assertion only, could be optimized away
- throw new AssertionFailure("entity was persistent");
+ throw new AssertionFailure( "entity was persistent" );
}
-
+
Object entity = event.getEntity();
EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), entity );
- event.setRequestedId( getUpdateId( entity, persister, event.getRequestedId(), event.getSession().getEntityMode() ) );
-
- performUpdate(event, entity, persister);
+ event.setRequestedId(
+ getUpdateId(
+ entity, persister, event.getRequestedId(), event.getSession().getEntityMode()
+ )
+ );
+ performUpdate( event, entity, persister );
+
}
-
- protected Serializable getUpdateId(Object entity, EntityPersister persister, Serializable requestedId, EntityMode entityMode)
- throws HibernateException {
+
+ /**
+ * Determine the id to use for updating.
+ *
+ * @param entity The entity.
+ * @param persister The entity persister
+ * @param requestedId The requested identifier
+ * @param entityMode The entity mode.
+ *
+ * @return The id.
+ *
+ * @throws TransientObjectException If the entity is considered transient.
+ */
+ protected Serializable getUpdateId(
+ Object entity,
+ EntityPersister persister,
+ Serializable requestedId,
+ EntityMode entityMode) {
// use the id assigned to the instance
- Serializable id = persister.getIdentifier(entity, entityMode);
- if ( id==null ) {
+ Serializable id = persister.getIdentifier( entity, entityMode );
+ if ( id == null ) {
// assume this is a newly instantiated transient object
// which should be saved rather than updated
throw new TransientObjectException(
"The given object has a null identifier: " +
- persister.getEntityName()
- );
+ persister.getEntityName()
+ );
}
else {
return id;
}
-
+
}
- protected void performUpdate(SaveOrUpdateEvent event, Object entity, EntityPersister persister)
- throws HibernateException {
-
+ protected void performUpdate(
+ SaveOrUpdateEvent event,
+ Object entity,
+ EntityPersister persister) throws HibernateException {
+
if ( !persister.isMutable() ) {
log.trace( "immutable instance passed to doUpdate(), locking" );
reassociate( event, entity, event.getRequestedId(), persister );
@@ -246,27 +269,29 @@
else {
if ( log.isTraceEnabled() ) {
- log.trace(
- "updating " +
- MessageHelper.infoString( persister, event.getRequestedId(), event.getSession().getFactory() )
- );
+ log.trace(
+ "updating " +
+ MessageHelper.infoString(
+ persister, event.getRequestedId(), event.getSession().getFactory()
+ )
+ );
}
-
+
final EventSource source = event.getSession();
-
+
EntityKey key = new EntityKey( event.getRequestedId(), persister, source.getEntityMode() );
-
+
source.getPersistenceContext().checkUniqueness( key, entity );
-
+
if ( invokeUpdateLifecycle( entity, persister, source ) ) {
reassociate( event, event.getObject(), event.getRequestedId(), persister );
return;
}
-
+
// this is a transient object with existing persistent state not loaded by the session
-
- new OnUpdateVisitor( source, event.getRequestedId() ).process( entity, persister );
-
+
+ new OnUpdateVisitor( source, event.getRequestedId(), entity ).process( entity, persister );
+
//TODO: put this stuff back in to read snapshot from
// the second-level cache (needs some extra work)
/*Object[] cachedState = null;
@@ -274,8 +299,8 @@
if ( persister.hasCache() ) {
CacheEntry entry = (CacheEntry) persister.getCache()
.get( event.getRequestedId(), source.getTimestamp() );
- cachedState = entry==null ?
- null :
+ cachedState = entry==null ?
+ null :
entry.getState(); //TODO: half-assemble this stuff
}*/
@@ -288,28 +313,28 @@
LockMode.NONE,
true,
persister,
- false,
+ false,
true //assume true, since we don't really know, and it doesn't matter
+ );
+
+ persister.afterReassociate( entity, source );
+
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ "updating " +
+ MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() )
);
-
- persister.afterReassociate(entity, source);
-
- if ( log.isTraceEnabled() ) {
- log.trace(
- "updating " +
- MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() )
- );
}
-
- cascadeOnUpdate(event, persister, entity);
-
+
+ cascadeOnUpdate( event, persister, entity );
+
}
}
protected boolean invokeUpdateLifecycle(Object entity, EntityPersister persister, EventSource source) {
if ( persister.implementsLifecycle( source.getEntityMode() ) ) {
log.debug( "calling onUpdate()" );
- if ( ( ( Lifecycle ) entity ).onUpdate(source) ) {
+ if ( ( ( Lifecycle ) entity ).onUpdate( source ) ) {
log.debug( "update vetoed by onUpdate()" );
return true;
}
@@ -329,8 +354,8 @@
EventSource source = event.getSession();
source.getPersistenceContext().incrementCascadeLevel();
try {
- new Cascade(CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source)
- .cascade(persister, entity);
+ new Cascade( CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source )
+ .cascade( persister, entity );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
Modified: trunk/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -14,60 +14,55 @@
* When a transient entity is passed to lock(), we must inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
- * existing snapshot
+ * existing snapshot
* 3. throw an exception for each "new" collection
*
* @author Gavin King
*/
public class OnLockVisitor extends ReattachVisitor {
- public OnLockVisitor(EventSource session, Serializable key) {
- super(session, key);
+ public OnLockVisitor(EventSource session, Serializable key, Object owner) {
+ super( session, key, owner );
}
- Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
+ Object processCollection(Object collection, CollectionType type) throws HibernateException {
SessionImplementor session = getSession();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
- if (collection==null) {
+ if ( collection == null ) {
//do nothing
}
else if ( collection instanceof PersistentCollection ) {
- PersistentCollection persistentCollection = (PersistentCollection) collection;
-
- if ( persistentCollection.setCurrentSession(session) ) {
-
- if ( isOwnerUnchanged( persistentCollection, persister, getKey() ) ) {
+ PersistentCollection persistentCollection = ( PersistentCollection ) collection;
+ if ( persistentCollection.setCurrentSession( session ) ) {
+ if ( isOwnerUnchanged( persistentCollection, persister, extractCollectionKeyFromOwner( persister ) ) ) {
// a "detached" collection that originally belonged to the same entity
if ( persistentCollection.isDirty() ) {
- throw new HibernateException("reassociated object has dirty collection");
+ throw new HibernateException( "reassociated object has dirty collection" );
}
- reattachCollection(persistentCollection, type);
+ reattachCollection( persistentCollection, type );
}
else {
// a "detached" collection that belonged to a different entity
- throw new HibernateException("reassociated object has dirty collection reference");
+ throw new HibernateException( "reassociated object has dirty collection reference" );
}
-
}
else {
// a collection loaded in the current session
// can not possibly be the collection belonging
// to the entity passed to update()
- throw new HibernateException("reassociated object has dirty collection reference");
+ throw new HibernateException( "reassociated object has dirty collection reference" );
}
-
}
else {
// brand new collection
//TODO: or an array!! we can't lock objects with arrays now??
- throw new HibernateException("reassociated object has dirty collection reference (or an array)");
+ throw new HibernateException( "reassociated object has dirty collection reference (or an array)" );
}
return null;
}
-
+
}
Modified: trunk/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -10,40 +10,43 @@
import org.hibernate.type.CollectionType;
/**
- * When an entity is passed to replicate(), and there is an existing row, we must
+ * When an entity is passed to replicate(), and there is an existing row, we must
* inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
- * existing snapshot
+ * existing snapshot
* 3. execute a collection removal (SQL DELETE) for each null collection property
- * or "new" collection
+ * or "new" collection
*
* @author Gavin King
*/
public class OnReplicateVisitor extends ReattachVisitor {
-
+
private boolean isUpdate;
-
- OnReplicateVisitor(EventSource session, Serializable key, boolean isUpdate) {
- super(session, key);
+
+ OnReplicateVisitor(EventSource session, Serializable key, Object owner, boolean isUpdate) {
+ super( session, key, owner );
this.isUpdate = isUpdate;
}
Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
-
- if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+ throws HibernateException {
+ if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+ return null;
+ }
+
EventSource session = getSession();
- Serializable key = getKey();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
- if (isUpdate) removeCollection(persister, key, session);
- if ( collection!=null && (collection instanceof PersistentCollection) ) {
- PersistentCollection wrapper = (PersistentCollection) collection;
- wrapper.setCurrentSession(session);
+ if ( isUpdate ) {
+ removeCollection( persister, extractCollectionKeyFromOwner( persister ), session );
+ }
+ if ( collection != null && ( collection instanceof PersistentCollection ) ) {
+ PersistentCollection wrapper = ( PersistentCollection ) collection;
+ wrapper.setCurrentSession( session );
if ( wrapper.wasInitialized() ) {
- session.getPersistenceContext().addNewCollection(persister, wrapper);
+ session.getPersistenceContext().addNewCollection( persister, wrapper );
}
else {
reattachCollection( wrapper, type );
Modified: trunk/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -21,51 +21,49 @@
*/
public class OnUpdateVisitor extends ReattachVisitor {
- OnUpdateVisitor(EventSource session, Serializable key) {
- super(session, key);
+ OnUpdateVisitor(EventSource session, Serializable key, Object owner) {
+ super( session, key, owner );
}
- Object processCollection(Object collection, CollectionType type)
- throws HibernateException {
-
- if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+ /**
+ * {@inheritDoc}
+ */
+ Object processCollection(Object collection, CollectionType type) throws HibernateException {
+ if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+ return null;
+ }
+
EventSource session = getSession();
- Serializable key = getKey();
CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
+ final Serializable collectionKey = extractCollectionKeyFromOwner( persister );
if ( collection!=null && (collection instanceof PersistentCollection) ) {
PersistentCollection wrapper = (PersistentCollection) collection;
-
if ( wrapper.setCurrentSession(session) ) {
//a "detached" collection!
-
- if ( !isOwnerUnchanged(wrapper, persister, key) ) {
+ if ( !isOwnerUnchanged( wrapper, persister, collectionKey ) ) {
// if the collection belonged to a different entity,
// clean up the existing state of the collection
- removeCollection(persister, key, session);
+ removeCollection( persister, collectionKey, session );
}
-
reattachCollection(wrapper, type);
}
else {
// a collection loaded in the current session
// can not possibly be the collection belonging
// to the entity passed to update()
- removeCollection(persister, key, session);
+ removeCollection(persister, collectionKey, session);
}
-
}
else {
// null or brand new collection
// this will also (inefficiently) handle arrays, which have
// no snapshot, so we can't do any better
- removeCollection(persister, key, session);
- //processArrayOrNewCollection(collection, type);
+ removeCollection(persister, collectionKey, session);
}
return null;
-
}
}
Modified: trunk/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -14,34 +14,51 @@
import org.hibernate.type.Type;
/**
- * Abstract superclass of visitors that reattach collections
+ * Abstract superclass of visitors that reattach collections.
+ *
* @author Gavin King
*/
public abstract class ReattachVisitor extends ProxyVisitor {
-
- private static final Log log = LogFactory.getLog(ReattachVisitor.class);
- private final Serializable key;
+ private static final Log log = LogFactory.getLog( ReattachVisitor.class );
- final Serializable getKey() {
- return key;
+ private final Serializable ownerIdentifier;
+ private final Object owner;
+
+ public ReattachVisitor(EventSource session, Serializable ownerIdentifier, Object owner) {
+ super( session );
+ this.ownerIdentifier = ownerIdentifier;
+ this.owner = owner;
}
- public ReattachVisitor(EventSource session, Serializable key) {
- super(session);
- this.key=key;
+ /**
+ * Retrieve the identifier of the entity being visited.
+ *
+ * @return The entity's identifier.
+ */
+ final Serializable getOwnerIdentifier() {
+ return ownerIdentifier;
}
- Object processComponent(Object component, AbstractComponentType componentType)
- throws HibernateException {
+ /**
+ * Retrieve the entity being visited.
+ *
+ * @return The entity.
+ */
+ final Object getOwner() {
+ return owner;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ Object processComponent(Object component, AbstractComponentType componentType) throws HibernateException {
Type[] types = componentType.getSubtypes();
- if (component==null) {
+ if ( component == null ) {
processValues( new Object[types.length], types );
}
else {
- super.processComponent(component, componentType);
- //processValues( componentType.getPropertyValues( component, getSession() ), types );
+ super.processComponent( component, componentType );
}
return null;
@@ -51,23 +68,36 @@
* Schedules a collection for deletion.
*
* @param role The persister representing the collection to be removed.
- * @param id The id of the entity containing the collection to be removed.
+ * @param collectionKey The collection key (differs from owner-id in the case of property-refs).
+ * @param source The session from which the request originated.
* @throws HibernateException
*/
- public void removeCollection(CollectionPersister role, Serializable id, EventSource source)
- throws HibernateException {
- if ( log.isTraceEnabled() )
+ void removeCollection(CollectionPersister role, Serializable collectionKey, EventSource source) throws HibernateException {
+ if ( log.isTraceEnabled() ) {
log.trace(
"collection dereferenced while transient " +
- MessageHelper.collectionInfoString( role, id, source.getFactory() )
+ MessageHelper.collectionInfoString( role, ownerIdentifier, source.getFactory() )
);
- /*if ( role.hasOrphanDelete() ) {
- throw new HibernateException(
- "You may not dereference a collection with cascade=\"all-delete-orphan\": " +
- MessageHelper.infoString(role, id)
- );
- }*/
- source.getActionQueue().addAction( new CollectionRemoveAction( null, role, id, false, source ) );
+ }
+ source.getActionQueue().addAction( new CollectionRemoveAction( null, role, collectionKey, false, source ) );
}
+ /**
+ * This version is slightly different for say
+ * {@link org.hibernate.type.CollectionType#getKeyOfOwner} in that here we
+ * need to assume that the owner is not yet associated with the session,
+ * and thus we cannot rely on the owner's EntityEntry snapshot...
+ *
+ * @param role The persister for the collection role being processed.
+ * @return
+ */
+ final Serializable extractCollectionKeyFromOwner(CollectionPersister role) {
+ if ( role.getCollectionType().useLHSPrimaryKey() ) {
+ return ownerIdentifier;
+ }
+ else {
+ return ( Serializable ) role.getOwnerEntityPersister().getPropertyValue( owner, role.getCollectionType().getLHSPropertyName(), getSession().getEntityMode() );
+ }
+
+ }
}
Modified: trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml 2006-12-07 21:53:10 UTC (rev 10948)
@@ -1,17 +1,17 @@
<?xml version="1.0"?>
-<!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Demonstrates the use of property-ref to map legacy data where
foreign keys reference something other than the primary key of
the associated entity. Here we show:
-
- (1) A one-to-one foreign key association (prefer primary key
+
+ (1) A one-to-one foreign key association (prefer primary key
associations)
-
+
(2) A bidirectional one-to-many association on a key that is
not the primary key (prefer associations from foreign keys
to primary keys)
@@ -20,57 +20,47 @@
<hibernate-mapping package="org.hibernate.test.propertyref.basic">
- <class name="Person">
- <id name="id">
- <generator class="hilo"/>
- </id>
-
- <property name="name" length="100"/>
- <property name="userId" column="person_userid" length="8" unique="true"/>
-
- <one-to-one name="address" property-ref="person" cascade="all" fetch="join"/>
-
- <set name="accounts" inverse="true">
- <key column="userId" property-ref="userId"/>
- <one-to-many class="Account"/>
- </set>
-
- <bag name="systems" table="USER_SYSTEM" lazy="false" inverse="false" cascade="all">
+ <class name="Person" table="PROPREF_PERS">
+ <id name="id">
+ <generator class="hilo"/>
+ </id>
+ <property name="name" length="100"/>
+ <property name="userId" column="person_userid" length="8" unique="true"/>
+ <one-to-one name="address" property-ref="person" cascade="all" fetch="join"/>
+ <set name="accounts" inverse="true">
+ <key column="userId" property-ref="userId"/>
+ <one-to-many class="Account"/>
+ </set>
+ <bag name="systems" table="USER_SYSTEM" lazy="true" inverse="false" cascade="all">
<key column="USER_ID" property-ref="userId" />
<element type="string" column="SYSTEM" />
</bag>
</class>
- <class name="Address">
- <id name="id">
- <generator class="hilo"/>
- </id>
+ <class name="Address" table="PROPREF_ADDR">
+ <id name="id">
+ <generator class="hilo"/>
+ </id>
+ <property name="address" length="300"/>
+ <property name="zip" length="5"/>
+ <property name="country" length="25"/>
+ <many-to-one name="person" unique="true" not-null="true"/>
+ </class>
- <property name="address" length="300"/>
- <property name="zip" length="5"/>
- <property name="country" length="25"/>
- <many-to-one name="person" unique="true" not-null="true"/>
- </class>
-
- <class name="Account">
- <id name="accountId" length="32">
- <generator class="uuid.hex"/>
- </id>
-
- <many-to-one name="user"
- column="userId"
- property-ref="userId"/>
-
- <property name="type" not-null="true"/>
-
- </class>
-
- <class name="Group" table="`Group`">
- <id name="name"/>
- <set name="users" table="UserGroup" cascade="save-update">
- <key column="groupName"/>
- <many-to-many column="userId" class="Person" property-ref="userId"/>
- </set>
- </class>
+ <class name="Account" table="PROPREF_ACCT">
+ <id name="accountId" length="32">
+ <generator class="uuid.hex"/>
+ </id>
+ <many-to-one name="user" column="userId" property-ref="userId"/>
+ <property name="type" not-null="true"/>
+ </class>
+ <class name="Group" table="PROPREF_GRP">
+ <id name="name"/>
+ <set name="users" table="PROPREF_USERGROUP" cascade="save-update">
+ <key column="groupName"/>
+ <many-to-many column="userId" class="Person" property-ref="userId"/>
+ </set>
+ </class>
+
</hibernate-mapping>
\ No newline at end of file
Modified: trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java 2006-12-07 21:36:31 UTC (rev 10947)
+++ trunk/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java 2006-12-07 21:53:10 UTC (rev 10948)
@@ -60,7 +60,7 @@
t = s.beginTransaction();
s.createQuery( "from Person" ).list();
s.clear();
- s.createSQLQuery( "select {p.*} from Person {p}" )
+ s.createSQLQuery( "select {p.*} from PROPREF_PERS {p}" )
.addEntity( "p", Person.class.getName() )
.list();
t.commit();
17 years, 4 months
Hibernate SVN: r10947 - in branches/Branch_3_2/HibernateExt: ejb ejb/doc/reference/en ejb/doc/reference/en/modules ejb/src/java/org/hibernate/ejb metadata metadata/doc/reference/en metadata/doc/reference/en/modules metadata/src/java/org/hibernate/annotations metadata/src/java/org/hibernate/cfg/annotations metadata/src/java/org/hibernate/validator
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2006-12-07 16:36:31 -0500 (Thu, 07 Dec 2006)
New Revision: 10947
Modified:
branches/Branch_3_2/HibernateExt/ejb/build.xml
branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/master.xml
branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/modules/configuration.xml
branches/Branch_3_2/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java
branches/Branch_3_2/HibernateExt/metadata/build.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/master.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/entity.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/setup.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/validator.xml
branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/annotations/ResultCheckStyle.java
branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java
branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/validator/NotEmptyValidator.java
Log:
Various docs adds-on and fixes
Version change
Modified: branches/Branch_3_2/HibernateExt/ejb/build.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/ejb/build.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/ejb/build.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -16,7 +16,7 @@
<!-- Name of project and version, used to create filenames -->
<property name="Name" value="Hibernate EntityManager"/>
<property name="name" value="hibernate-entitymanager"/>
- <property name="version" value="3.2.0.GA"/>
+ <property name="version" value="3.2.1.GA"/>
<property name="javadoc.packagenames" value="org.hibernate.ejb.*"/>
<property name="jdbc.dir" value="jdbc"/>
<property name="copy.test" value="true"/>
Modified: branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/master.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/master.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/master.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -16,7 +16,7 @@
<subtitle>User guide</subtitle>
- <releaseinfo>3.2.0.GA</releaseinfo>
+ <releaseinfo>3.2.1.GA</releaseinfo>
<mediaobject>
<imageobject>
Modified: branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/modules/configuration.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/ejb/doc/reference/en/modules/configuration.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -8,18 +8,17 @@
<para>The EJB 3.0 / JPA compatible Hibernate EntityManager is built on top
of Hibernate core and Hibernate Annotations. You have to use compatible
versions of each module. This version is known to work on Hibernate Core
- 3.2.0.CR5 and 3.2.0.GA and Hibernate Annotations
- 3.2.0.CR3 and 3.2.0.GA. The following libraries have to be in your classpath:
- hibernate3.jar, hibernate-annotations.jar, hibernate-entitymanager.jar and
- all needed third party libraries for each package.(incl.
- ejb-persistence.jar).</para>
+ 3.2.0.CR5, 3.2.0.GA, 3.2.1.GA and Hibernate Annotations 3.2.0.CR3, 3.2.0.GA, 3.2.1.GA.
+ The following libraries have to be in your classpath: hibernate3.jar,
+ hibernate-annotations.jar, hibernate-entitymanager.jar and all needed
+ third party libraries for each package.(incl. ejb-persistence.jar).</para>
</section>
<section id="setup-configuration"
xreflabel="Configuration and bootstrapping">
<title>Configuration and bootstrapping</title>
- <section id="setup-configuration-packaging">
+ <section id="setup-configuration-packaging" revision="1">
<title>Packaging</title>
<para>The configuration for entity managers both inside an application
@@ -87,7 +86,9 @@
<listitem>
<para>(attribute) Transaction type used. Either JTA or
RESOURCE_LOCAL (default to JTA in a JavaEE environment and to
- RESOURCE_LOCAL in a JavaSE environment).</para>
+ RESOURCE_LOCAL in a JavaSE environment). When a jta-datasource is
+ used, the default is JTA, if non-jta-datasource is used,
+ RESOURCE_LOCAL is used.</para>
</listitem>
</varlistentry>
@@ -145,7 +146,12 @@
files part of this jar file will be added to the persistence unit
configuration. This element is mainly used in Java EE environment.
Use of this one in Java SE should be considered as non portable,
- in this case a absolute url is needed.</para>
+ in this case a absolute url is needed. You can alternatively point
+ to a directory (This is especially useful when in your test
+ environment, the persistence.xml file is not under the same root
+ directory or jar than your domain model).</para>
+
+ <programlisting> <jar-file>file:/home/turin/work/local/lab8/build/classes</jar-file></programlisting>
</listitem>
</varlistentry>
@@ -173,7 +179,10 @@
through the class element though. As an extension to the
specification, you can add a package name in the
<literal><class></literal> element (eg
- <code><class>org.hibernate.eg</class></code>).</para>
+ <code><class>org.hibernate.eg</class></code>).
+ Caution, the package will include the metadata defined at the
+ package level (ie in <filename>package-info.java</filename>), it
+ will not include all the classes of a given package.</para>
</listitem>
</varlistentry>
@@ -204,7 +213,7 @@
version="1.0"></programlisting>
</section>
- <section id="setup-configuration-bootstrapping">
+ <section id="setup-configuration-bootstrapping" revision="1">
<title>Bootstrapping</title>
<para>The EJB3 specification defines a bootstrap procedure to access the
@@ -411,7 +420,7 @@
<!-- alternatively to <class> and <property> declarations, you can use a regular hibernate.cfg.xml file -->
<!-- property name="hibernate.ejb.cfgfile" value="/org/hibernate/ejb/test/hibernate.cfg.xml"/ -->
</properties>
- <persistence-unit>
+ </persistence-unit>
</persistence></programlisting>
<para>To ease the programmatic configuration, Hibernate Entity Manager
Modified: branches/Branch_3_2/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java
===================================================================
--- branches/Branch_3_2/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/ejb/src/java/org/hibernate/ejb/Version.java 2006-12-07 21:36:31 UTC (rev 10947)
@@ -8,7 +8,7 @@
* @author Emmanuel Bernard
*/
public class Version {
- public static final String VERSION = "3.2.0.GA";
+ public static final String VERSION = "3.2.1.GA";
private static Log log = LogFactory.getLog( Version.class );
static {
Modified: branches/Branch_3_2/HibernateExt/metadata/build.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/build.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/build.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -16,7 +16,7 @@
<!-- Name of project and version, used to create filenames -->
<property name="Name" value="Hibernate Annotations"/>
<property name="name" value="hibernate-annotations"/>
- <property name="version" value="3.2.0.GA"/>
+ <property name="version" value="3.2.1.GA"/>
<property name="javadoc.packagenames" value="org.hibernate.*"/>
<property name="jdbc.dir" value="jdbc"/>
<property name="copy.test" value="true"/>
Modified: branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/master.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/master.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/master.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -13,7 +13,7 @@
<subtitle>Reference Guide</subtitle>
- <releaseinfo>3.2.0.GA</releaseinfo>
+ <releaseinfo>3.2.1.GA</releaseinfo>
<mediaobject>
<imageobject>
Modified: branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/entity.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -1714,7 +1714,7 @@
<literal>LAZY</literal> and <literal>@OneToOne</literal> and
<literal>@ManyToOne</literal> are defaulted to
<literal>EAGER</literal>. For more information about static fetching,
- check <xref linkend="entity-hibspec-singleassoc-fetching" />. </para>
+ check <xref linkend="entity-hibspec-singleassoc-fetching" />.</para>
<para>The recommanded approach is to use <literal>LAZY</literal> onn
all static fetching definitions and override this choice dynamically
@@ -2623,6 +2623,25 @@
<literal>@Generated(INSERT)</literal> by design, it has to be either
<literal>NEVER</literal> or <literal>ALWAYS</literal>.</para>
</sect3>
+
+ <sect3>
+ <title>@Target</title>
+
+ <para>Sometimes, the type guessed by reflection is not the one you
+ want Hibernate to use. This is especially true on components when an
+ interface is used. You can use <literal>@Target</literal> to by pass
+ the reflection guessing mechanism (very much like the
+ <literal>targetEntity</literal> attribute available on
+ associations.</para>
+
+ <programlisting> @Embedded
+ <emphasis role="bold">@Target(OwnerImpl.class)</emphasis>
+ public Owner getOwner() {
+ return owner;
+ }</programlisting>
+
+ <para></para>
+ </sect3>
</sect2>
<sect2 id="entity-hibspec-inheritance" revision="1">
@@ -2903,7 +2922,7 @@
</note>
</sect4>
- <sect4>
+ <sect4 id="entity-hibspec-collection-extratype-map" revision="1">
<title>Map</title>
<para>Hibernate Annotations also supports true Map mappings, if
@@ -2915,6 +2934,18 @@
embeddable object, or you can use
<literal>@org.hibernate.annotations.MapKeyManyToMany</literal> if
your key is an entity.</para>
+
+ <para>Both <literal>@org.hibernate.annotations.MapKey</literal> and
+ <literal>@org.hibernate.annotations.MapKeyManyToMany</literal>
+ allows you to override the target element to be used. This is
+ especially useful if your collection does not use generics (or if
+ you use interfaces).</para>
+
+ <programlisting> @CollectionOfElements(targetElement = SizeImpl.class)
+ @MapKeyManyToMany(<emphasis role="bold">targetEntity = LuggageImpl.class</emphasis>)
+ private Map<Luggage, Size> sizePerLuggage = new HashMap<Luggage, Size>();</programlisting>
+
+ <para></para>
</sect4>
<sect4 id="entity-hibspec-collection-extratype-indexbidir">
@@ -3319,5 +3350,84 @@
detyped <literal>@QueryHint</literal>. Another key advantage is the
ability to set those annotations at a package level.</para>
</sect2>
+
+ <sect2 id="entity-hibspec-customsql">
+ <title>Custom SQL for CRUD operations</title>
+
+ <para>Hibernate gives you the avility to override every single SQL
+ statement generated. We have seen native SQL query usage already, but
+ you can also override the SQL statement used to load or change the state
+ of entities.</para>
+
+ <programlisting>@Entity
+@Table(name="CHAOS")
+<emphasis role="bold">@SQLInsert( sql="INSERT INTO CHAOS(size, name, nickname, id) VALUES(?,upper(?),?,?)")
+@SQLUpdate( sql="UPDATE CHAOS SET size = ?, name = upper(?), nickname = ? WHERE id = ?")
+@SQLDelete( sql="DELETE CHAOS WHERE id = ?")
+@SQLDeleteAll( sql="DELETE CHAOS")
+</emphasis><emphasis role="bold">@Loader(namedQuery = "chaos")</emphasis>
+@NamedNativeQuery(name="chaos", query="select id, size, name, lower( nickname ) as nickname from CHAOS where id= ?", resultClass = Chaos.class)
+public class Chaos {
+ @Id
+ private Long id;
+ private Long size;
+ private String name;
+ private String nickname;</programlisting>
+
+ <para><literal>@SQLInsert</literal>, <literal>@SQLUpdate</literal>,
+ <literal>@SQLDelete</literal>, <literal>@SQLDeleteAll</literal>
+ respectively override the INSERT statement, UPDATE statement, DELETE
+ statement, DELETE statement to remove all entities.</para>
+
+ <para>If you expect to call a store procedure, be sure to set the
+ <literal>callable</literal> attribute to true
+ (<literal>@SQLInsert(callable=true, ...)</literal>).</para>
+
+ <para>To check that the execution happens correctly, Hibernate allows
+ you to define one of those three strategies:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>NONE: no check is performed: the store procedure is expected
+ to fail upon issues</para>
+ </listitem>
+
+ <listitem>
+ <para>COUNT: use of rowcount to check that the update is
+ successful</para>
+ </listitem>
+
+ <listitem>
+ <para>PARAM: like COUNT but using an output parameter rather that
+ the standard mechanism</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>To define the result check style, use the <literal>check</literal>
+ parameter (<literal>@SQLUpdate(check=ResultCheckStyle.COUNT,
+ ...)</literal>).</para>
+
+ <para>You can also override the SQL load statement by a native SQL query
+ or a HQL query. You just have to refer to a named query with the
+ <literal><literal>@Loader</literal></literal> annotation.</para>
+
+ <para>You can use the exact same set of annotations to override the
+ collection related statements.</para>
+
+ <programlisting>@OneToMany
+@JoinColumn(name="chaos_fk")
+<emphasis role="bold">@SQLInsert( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = ? where id = ?")
+@SQLDelete( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = null where id = ?")</emphasis>
+private Set<CasimirParticle> particles = new HashSet<CasimirParticle>();</programlisting>
+
+ <para>The parameters order is important and is defined by the order
+ Hibernate handle properties. You can see the expected order by enabling
+ debug logging for the <literal>org.hibernate.persister.entity</literal>
+ level. With this level enabled Hibernate will print out the static SQL
+ that is used to create, update, delete etc. entities. (To see the
+ expected sequence, remember to not include your custom SQL through
+ annotations as that will override the Hibernate generated static
+ sql.)</para>
+ </sect2>
</sect1>
</chapter>
\ No newline at end of file
Modified: branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/setup.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/setup.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/setup.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -18,8 +18,8 @@
</listitem>
<listitem>
- <para>This release is known to work on Hibernate core 3.2.0.CR5
- and 3.2.0.GA</para>
+ <para>This release is known to work on Hibernate core 3.2.0.CR5, 3.2.0.GA
+ and 3.2.1.GA</para>
</listitem>
<listitem>
Modified: branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/validator.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/validator.xml 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/en/modules/validator.xml 2006-12-07 21:36:31 UTC (rev 10947)
@@ -45,7 +45,7 @@
constraint apply to the annotated element.</para>
</sect2>
- <sect2>
+ <sect2 id="validator-constraints-built-in" revision="1">
<title>Built in constraints</title>
<para>Hibernate Validator comes with some built-in constraints, which
@@ -114,6 +114,17 @@
</row>
<row>
+ <entry>@NotEmpty</entry>
+
+ <entry>property</entry>
+
+ <entry>check if the string is not null nor empty. Check if the
+ connection is not null nor empty</entry>
+
+ <entry>Column(s) are not null (for String)</entry>
+ </row>
+
+ <row>
<entry>@Past</entry>
<entry>property (date or calendar)</entry>
Modified: branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/annotations/ResultCheckStyle.java
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/annotations/ResultCheckStyle.java 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/annotations/ResultCheckStyle.java 2006-12-07 21:36:31 UTC (rev 10947)
@@ -7,7 +7,25 @@
* @author L�szl� Benke
*/
public enum ResultCheckStyle {
+ /**
+ * Do not perform checking. Either user simply does not want checking, or is
+ * indicating a {@link java.sql.CallableStatement} execution in which the
+ * checks are being performed explicitly and failures are handled through
+ * propogation of {@link java.sql.SQLException}s.
+ */
NONE,
+ /**
+ * Perform row-count checking. Row counts are the int values returned by both
+ * {@link java.sql.PreparedStatement#executeUpdate()} and
+ * {@link java.sql.Statement#executeBatch()}. These values are checked
+ * against some expected count.
+ */
COUNT,
+ /**
+ * Essentially the same as {@link #COUNT} except that the row count actually
+ * comes from an output parameter registered as part of a
+ * {@link java.sql.CallableStatement}. This style explicitly prohibits
+ * statement batching from being used...
+ */
PARAM
}
Modified: branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/cfg/annotations/Version.java 2006-12-07 21:36:31 UTC (rev 10947)
@@ -8,7 +8,7 @@
* @author Emmanuel Bernard
*/
public class Version {
- public static final String VERSION = "3.2.1-dev";
+ public static final String VERSION = "3.2.1.GA";
private static Log log = LogFactory.getLog( Version.class );
static {
Modified: branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/validator/NotEmptyValidator.java
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/validator/NotEmptyValidator.java 2006-12-07 14:50:59 UTC (rev 10946)
+++ branches/Branch_3_2/HibernateExt/metadata/src/java/org/hibernate/validator/NotEmptyValidator.java 2006-12-07 21:36:31 UTC (rev 10947)
@@ -5,13 +5,18 @@
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
+import java.util.Iterator;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.SingleTableSubclass;
+import org.hibernate.mapping.Column;
+
/**
* Check the non emptyness of the element
*
* @author Gavin King
*/
-public class NotEmptyValidator implements Validator<NotEmpty>, Serializable {
+public class NotEmptyValidator implements Validator<NotEmpty>, PropertyConstraint, Serializable {
public void initialize(NotEmpty parameters) {
}
@@ -32,4 +37,18 @@
}
}
+ @SuppressWarnings("unchecked")
+ public void apply(Property property) {
+ if ( ! ( property.getPersistentClass() instanceof SingleTableSubclass )
+ && ! ( property.getValue() instanceof Collection ) ) {
+ //single table should not be forced to null
+ if ( !property.isComposite() ) { //composite should not add not-null on all columns
+ Iterator<Column> iter = (Iterator<Column>) property.getColumnIterator();
+ while ( iter.hasNext() ) {
+ iter.next().setNullable( false );
+ }
+ }
+ }
+ }
+
}
17 years, 4 months
Hibernate SVN: r10946 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/hql/ast test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 09:50:59 -0500 (Thu, 07 Dec 2006)
New Revision: 10946
Added:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java
Log:
specialized InvalidWithClauseException
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-12-07 14:50:42 UTC (rev 10945)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-12-07 14:50:59 UTC (rev 10946)
@@ -15,7 +15,6 @@
import org.apache.commons.logging.LogFactory;
import org.hibernate.QueryException;
import org.hibernate.HibernateException;
-import org.hibernate.impl.FilterImpl;
import org.hibernate.engine.JoinSequence;
import org.hibernate.engine.ParameterBinder;
import org.hibernate.engine.SessionFactoryImplementor;
@@ -62,7 +61,6 @@
import org.hibernate.param.PositionalParameterSpecification;
import org.hibernate.param.VersionTypeSeedParameterSpecification;
import org.hibernate.param.CollectionFilterKeyParameterSpecification;
-import org.hibernate.param.DynamicFilterParameterSpecification;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinFragment;
@@ -336,7 +334,7 @@
traverser.traverseDepthFirst( hqlSqlWithNode );
FromElement referencedFromElement = visitor.getReferencedFromElement();
if ( referencedFromElement != fromElement ) {
- throw new SemanticException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" );
+ throw new InvalidWithClauseException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" );
}
SqlGenerator sql = new SqlGenerator( getSessionFactoryHelper().getFactory() );
sql.whereExpr( hqlSqlWithNode.getFirstChild() );
@@ -346,6 +344,9 @@
catch( SemanticException e ) {
throw e;
}
+ catch( InvalidWithClauseException e ) {
+ throw e;
+ }
catch ( Exception e) {
throw new SemanticException( e.getMessage() );
}
@@ -383,7 +384,7 @@
// creates and renders the join fragments for inheritence
// hierarchies...
if ( !joinAlias.equals( referencedFromElement.getTableAlias() ) ) {
- throw new HibernateException( "with clause can only reference columns in the driving table" );
+ throw new InvalidWithClauseException( "with clause can only reference columns in the driving table" );
}
}
}
Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java 2006-12-07 14:50:42 UTC (rev 10945)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java 2006-12-07 14:50:59 UTC (rev 10946)
@@ -0,0 +1,18 @@
+package org.hibernate.hql.ast;
+
+import org.hibernate.QueryException;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class InvalidWithClauseException extends QuerySyntaxException {
+ public InvalidWithClauseException(String message) {
+ super( message );
+ }
+
+ public InvalidWithClauseException(String message, String queryString) {
+ super( message, queryString );
+ }
+}
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java 2006-12-07 14:50:42 UTC (rev 10945)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java 2006-12-07 14:50:59 UTC (rev 10946)
@@ -6,6 +6,7 @@
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
+import org.hibernate.hql.ast.InvalidWithClauseException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
@@ -76,10 +77,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "can only reference columns in the driving table" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
try {
@@ -87,10 +85,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "with-clause expressions did not reference from-clause element to which the with-clause was associated" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
try {
@@ -99,10 +94,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "with-clause expressions did not reference from-clause element to which the with-clause was associated" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
txn.commit();
17 years, 4 months
Hibernate SVN: r10945 - in trunk/Hibernate3: src/org/hibernate/hql/ast test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 09:50:42 -0500 (Thu, 07 Dec 2006)
New Revision: 10945
Added:
trunk/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java
Modified:
trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java
trunk/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java
Log:
specialized InvalidWithClauseException
Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-12-07 14:22:54 UTC (rev 10944)
+++ trunk/Hibernate3/src/org/hibernate/hql/ast/HqlSqlWalker.java 2006-12-07 14:50:42 UTC (rev 10945)
@@ -333,7 +333,7 @@
traverser.traverseDepthFirst( hqlSqlWithNode );
FromElement referencedFromElement = visitor.getReferencedFromElement();
if ( referencedFromElement != fromElement ) {
- throw new SemanticException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" );
+ throw new InvalidWithClauseException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" );
}
SqlGenerator sql = new SqlGenerator( getSessionFactoryHelper().getFactory() );
sql.whereExpr( hqlSqlWithNode.getFirstChild() );
@@ -343,6 +343,9 @@
catch( SemanticException e ) {
throw e;
}
+ catch( InvalidWithClauseException e ) {
+ throw e;
+ }
catch ( Exception e) {
throw new SemanticException( e.getMessage() );
}
@@ -380,7 +383,7 @@
// creates and renders the join fragments for inheritence
// hierarchies...
if ( !joinAlias.equals( referencedFromElement.getTableAlias() ) ) {
- throw new HibernateException( "with clause can only reference columns in the driving table" );
+ throw new InvalidWithClauseException( "with clause can only reference columns in the driving table" );
}
}
}
Added: trunk/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java 2006-12-07 14:22:54 UTC (rev 10944)
+++ trunk/Hibernate3/src/org/hibernate/hql/ast/InvalidWithClauseException.java 2006-12-07 14:50:42 UTC (rev 10945)
@@ -0,0 +1,18 @@
+package org.hibernate.hql.ast;
+
+import org.hibernate.QueryException;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class InvalidWithClauseException extends QuerySyntaxException {
+ public InvalidWithClauseException(String message) {
+ super( message );
+ }
+
+ public InvalidWithClauseException(String message, String queryString) {
+ super( message, queryString );
+ }
+}
Modified: trunk/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java 2006-12-07 14:22:54 UTC (rev 10944)
+++ trunk/Hibernate3/test/org/hibernate/test/hql/WithClauseTest.java 2006-12-07 14:50:42 UTC (rev 10945)
@@ -6,6 +6,7 @@
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
+import org.hibernate.hql.ast.InvalidWithClauseException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
@@ -76,10 +77,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "can only reference columns in the driving table" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
try {
@@ -87,10 +85,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "with-clause expressions did not reference from-clause element to which the with-clause was associated" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
try {
@@ -99,10 +94,7 @@
.list();
fail( "failure expected" );
}
- catch( QueryException qe ) {
- if ( qe.getMessage().indexOf( "with-clause expressions did not reference from-clause element to which the with-clause was associated" ) < 0 ) {
- fail( "unexpected failure type [" + qe.getMessage() + "]" );
- }
+ catch( InvalidWithClauseException expected ) {
}
txn.commit();
17 years, 4 months
Hibernate SVN: r10944 - branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 09:22:54 -0500 (Thu, 07 Dec 2006)
New Revision: 10944
Modified:
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
Log:
removed FailureExpected
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 14:22:43 UTC (rev 10943)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 14:22:54 UTC (rev 10944)
@@ -514,7 +514,7 @@
s.close();
}
- public void testFetchInSubqueryFailureExpected() {
+ public void testFetchInSubqueryFails() {
Session s = openSession();
try {
s.createQuery( "from Animal a where a.mother in (select m from Animal a1 inner join a1.mother as m join fetch m.mother)" ).list();
17 years, 4 months
Hibernate SVN: r10943 - trunk/Hibernate3/test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 09:22:43 -0500 (Thu, 07 Dec 2006)
New Revision: 10943
Modified:
trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
Log:
removed FailureExpected
Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 13:49:42 UTC (rev 10942)
+++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 14:22:43 UTC (rev 10943)
@@ -513,7 +513,7 @@
s.close();
}
- public void testFetchInSubqueryFailureExpected() {
+ public void testFetchInSubqueryFails() {
Session s = openSession();
try {
s.createQuery( "from Animal a where a.mother in (select m from Animal a1 inner join a1.mother as m join fetch m.mother)" ).list();
17 years, 4 months
Hibernate SVN: r10942 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/hql/ast/tree test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 08:49:42 -0500 (Thu, 07 Dec 2006)
New Revision: 10942
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
Log:
test failures - shallow + implicit joins
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-12-07 13:49:22 UTC (rev 10941)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-12-07 13:49:42 UTC (rev 10942)
@@ -32,9 +32,13 @@
*/
public class DotNode extends FromReferenceNode implements DisplayableNode, SelectExpression {
- /**
- * A logger for this class.
- */
+ ///////////////////////////////////////////////////////////////////////////
+ // USED ONLY FOR REGRESSION TESTING!!!!
+ ///////////////////////////////////////////////////////////////////////////
+ public static boolean useThetaStyleImplicitJoins = false;
+ public static boolean REGRESSION_STYLE_JOIN_SUPPRESSION = false;
+ ///////////////////////////////////////////////////////////////////////////
+
private static final Log log = LogFactory.getLog( DotNode.class );
private static final int DEREF_UNKNOWN = 0;
@@ -285,20 +289,26 @@
private void dereferenceEntity(EntityType entityType, boolean implicitJoin, String classAlias, boolean generateJoin, AST parent) throws SemanticException {
checkForCorrelatedSubquery( "dereferenceEntity" );
-
- // three general cases we check here:
+ // three general cases we check here as to whether to render a physical SQL join:
// 1) is our parent a DotNode as well? If so, our property reference is
// being further de-referenced...
// 2) is this a DML statement
// 3) we were asked to generate any needed joins (generateJoins==true) *OR*
- // the current parser state indicates to use an INNER JOIN for implicit joins
+ // we are currently processing a select or from clause
+ // (an additional check is the REGRESSION_STYLE_JOIN_SUPPRESSION check solely intended for the test suite)
//
- // The "implicit join" portion of the second condition was done to account for
- // situations like HHH-2257 to make sure that iterate() and list() return
- // consistent results. Previously the join would be skipped on "shallow queries"
- // (aka, iterate()) for performance reasons, but that can lead to incorrect
- // results since INNER JOINs do place extra restrications on the returned
- // results.
+ // The REGRESSION_STYLE_JOIN_SUPPRESSION is an additional check
+ // intended solely for use within the test suite. This forces the
+ // implicit join resolution to behave more like the classic parser.
+ // The underlying issue is that classic translator is simply wrong
+ // about its decisions on whether or not to render an implicit join
+ // into a physical SQL join in a lot of cases. The piece it generally
+ // tends to miss is that INNER joins effect the results by further
+ // restricting the data set! A particular manifestation of this is
+ // the fact that the classic translator will skip the physical join
+ // for ToOne implicit joins *if the query is shallow*; the result
+ // being that Query.list() and Query.iterate() could return
+ // different number of results!
DotNode parentAsDotNode = null;
String property = propertyName;
final boolean joinIsNeeded;
@@ -314,10 +324,12 @@
else if ( ! getWalker().isSelectStatement() ) {
joinIsNeeded = false;
}
+ else if ( REGRESSION_STYLE_JOIN_SUPPRESSION ) {
+ // this is the regression style determination which matches the logic of the classic translator
+ joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() );
+ }
else {
- // otherwise we need to generate the join if we were asked to, or
- // if the current implicit join type is INNER JOINs
- joinIsNeeded = generateJoin || getWalker().getImpliedJoinType() == JoinFragment.INNER_JOIN;
+ joinIsNeeded = generateJoin || ( getWalker().isInSelect() || getWalker().isInFrom() );
}
if ( joinIsNeeded ) {
@@ -623,11 +635,6 @@
lhs = ( FromReferenceNode ) lhs.getFirstChild();
}
}
-
- /**
- * Used ONLY for regression testing!
- */
- public static boolean useThetaStyleImplicitJoins = false;
public void setResolvedConstant(String text) {
path = text;
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 13:49:22 UTC (rev 10941)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 13:49:42 UTC (rev 10942)
@@ -23,6 +23,7 @@
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.TypeMismatchException;
+import org.hibernate.hql.ast.tree.DotNode;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.DB2Dialect;
@@ -77,6 +78,7 @@
"hql/Animal.hbm.xml",
"hql/FooBarCopy.hbm.xml",
"hql/SimpleEntityWithAssociation.hbm.xml",
+ "hql/CrazyIdFieldNames.hbm.xml",
"batchfetch/ProductLine.hbm.xml",
"cid/Customer.hbm.xml",
"cid/Order.hbm.xml",
@@ -94,6 +96,41 @@
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
}
+ public void testCrazyIdFieldNames() {
+ MoreCrazyIdFieldNameStuffEntity top = new MoreCrazyIdFieldNameStuffEntity( "top" );
+ HeresAnotherCrazyIdFieldName next = new HeresAnotherCrazyIdFieldName( "next" );
+ top.setHeresAnotherCrazyIdFieldName( next );
+ MoreCrazyIdFieldNameStuffEntity other = new MoreCrazyIdFieldNameStuffEntity( "other" );
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( next );
+ s.save( top );
+ s.save( other );
+ s.flush();
+
+ List results = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e where e.heresAnotherCrazyIdFieldName is not null" ).list();
+ assertEquals( 1, results.size() );
+ Object result = results.get( 0 );
+ assertClassAssignability( HeresAnotherCrazyIdFieldName.class, result.getClass() );
+ assertSame( next, result );
+
+ results = s.createQuery( "select e.heresAnotherCrazyIdFieldName.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e where e.heresAnotherCrazyIdFieldName is not null" ).list();
+ assertEquals( 1, results.size() );
+ result = results.get( 0 );
+ assertClassAssignability( Long.class, result.getClass() );
+ assertEquals( next.getHeresAnotherCrazyIdFieldName(), result );
+
+ results = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e" ).list();
+ assertEquals( 1, results.size() );
+ Iterator itr = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e" ).iterate();
+ assertEquals( 1, determineCount( itr ) );
+
+ s.delete( top );
+ s.delete( next );
+ s.getTransaction().commit();
+ s.close();
+ }
+
public void testImplicitJoinsInDifferentClauses() {
// HHH-2257 :
// both the classic and ast translators output the same syntactically valid sql
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml 2006-12-07 13:49:22 UTC (rev 10941)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml 2006-12-07 13:49:42 UTC (rev 10942)
@@ -4,16 +4,16 @@
<hibernate-mapping package="org.hibernate.test.hql">
- <class name="HeresAnotherCrazyIdFieldName">
+ <class name="HeresAnotherCrazyIdFieldName" table="CRAZY_ID_NODE">
<id name="heresAnotherCrazyIdFieldName" column="ID" type="long">
- <generator class="native"/>
+ <generator class="increment"/>
</id>
<property name="name" type="string"/>
</class>
- <class name="MoreCrazyIdFieldNameStuffEntity">
+ <class name="MoreCrazyIdFieldNameStuffEntity" table="CRAZY_ID_TOP">
<id name="moreCrazyIdFieldNameStuffEntity" column="ID" type="long">
- <generator class="native"/>
+ <generator class="increment"/>
</id>
<property name="name" type="string" />
<many-to-one name="heresAnotherCrazyIdFieldName" class="HeresAnotherCrazyIdFieldName"/>
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-12-07 13:49:22 UTC (rev 10941)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-12-07 13:49:42 UTC (rev 10942)
@@ -43,13 +43,24 @@
public HQLTest(String x) {
super( x );
- SelectClause.VERSION2_SQL = true;
}
protected boolean dropAfterFailure() {
return false;
}
+ protected void setUp() throws Exception {
+ super.setUp();
+ SelectClause.VERSION2_SQL = true;
+ DotNode.REGRESSION_STYLE_JOIN_SUPPRESSION = true;
+ }
+
+ protected void tearDown() throws Exception {
+ SelectClause.VERSION2_SQL = false;
+ DotNode.REGRESSION_STYLE_JOIN_SUPPRESSION = false;
+ super.tearDown();
+ }
+
//FAILING TESTS:
public void testSubComponentReferences() {
17 years, 4 months
Hibernate SVN: r10941 - in trunk/Hibernate3: src/org/hibernate/hql/ast/tree test/org/hibernate/test/hql
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 08:49:22 -0500 (Thu, 07 Dec 2006)
New Revision: 10941
Modified:
trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
trunk/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml
trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
Log:
test failures - shallow + implicit joins
Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-12-07 12:59:25 UTC (rev 10940)
+++ trunk/Hibernate3/src/org/hibernate/hql/ast/tree/DotNode.java 2006-12-07 13:49:22 UTC (rev 10941)
@@ -25,16 +25,18 @@
/**
* Represents a reference to a property or alias expression. This should duplicate the relevant behaviors in
* PathExpressionParser.
- * <hr>
- * User: josh<br>
- * Date: Dec 16, 2003<br>
- * Time: 8:03:09 AM
+ *
+ * @author Joshua Davis
*/
public class DotNode extends FromReferenceNode implements DisplayableNode, SelectExpression {
- /**
- * A logger for this class.
- */
+ ///////////////////////////////////////////////////////////////////////////
+ // USED ONLY FOR REGRESSION TESTING!!!!
+ ///////////////////////////////////////////////////////////////////////////
+ public static boolean useThetaStyleImplicitJoins = false;
+ public static boolean REGRESSION_STYLE_JOIN_SUPPRESSION = false;
+ ///////////////////////////////////////////////////////////////////////////
+
private static final Log log = LogFactory.getLog( DotNode.class );
private static final int DEREF_UNKNOWN = 0;
@@ -285,19 +287,26 @@
private void dereferenceEntity(EntityType entityType, boolean implicitJoin, String classAlias, boolean generateJoin, AST parent) throws SemanticException {
checkForCorrelatedSubquery( "dereferenceEntity" );
- // three general cases we check here:
+ // three general cases we check here as to whether to render a physical SQL join:
// 1) is our parent a DotNode as well? If so, our property reference is
// being further de-referenced...
// 2) is this a DML statement
// 3) we were asked to generate any needed joins (generateJoins==true) *OR*
- // the current parser state indicates to use an INNER JOIN for implicit joins
+ // we are currently processing a select or from clause
+ // (an additional check is the REGRESSION_STYLE_JOIN_SUPPRESSION check solely intended for the test suite)
//
- // The "implicit join" portion of the second condition was done to account for
- // situations like HHH-2257 to make sure that iterate() and list() return
- // consistent results. Previously the join would be skipped on "shallow queries"
- // (aka, iterate()) for performance reasons, but that can lead to incorrect
- // results since INNER JOINs do place extra restrications on the returned
- // results.
+ // The REGRESSION_STYLE_JOIN_SUPPRESSION is an additional check
+ // intended solely for use within the test suite. This forces the
+ // implicit join resolution to behave more like the classic parser.
+ // The underlying issue is that classic translator is simply wrong
+ // about its decisions on whether or not to render an implicit join
+ // into a physical SQL join in a lot of cases. The piece it generally
+ // tends to miss is that INNER joins effect the results by further
+ // restricting the data set! A particular manifestation of this is
+ // the fact that the classic translator will skip the physical join
+ // for ToOne implicit joins *if the query is shallow*; the result
+ // being that Query.list() and Query.iterate() could return
+ // different number of results!
DotNode parentAsDotNode = null;
String property = propertyName;
final boolean joinIsNeeded;
@@ -313,10 +322,12 @@
else if ( ! getWalker().isSelectStatement() ) {
joinIsNeeded = false;
}
+ else if ( REGRESSION_STYLE_JOIN_SUPPRESSION ) {
+ // this is the regression style determination which matches the logic of the classic translator
+ joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() );
+ }
else {
- // otherwise we need to generate the join if we were asked to, or
- // if the current implicit join type is INNER JOINs
- joinIsNeeded = generateJoin || getWalker().getImpliedJoinType() == JoinFragment.INNER_JOIN;
+ joinIsNeeded = generateJoin || ( getWalker().isInSelect() || getWalker().isInFrom() );
}
if ( joinIsNeeded ) {
@@ -623,11 +634,6 @@
}
}
- /**
- * Used ONLY for regression testing!
- */
- public static boolean useThetaStyleImplicitJoins = false;
-
public void setResolvedConstant(String text) {
path = text;
dereferenceType = DEREF_JAVA_CONSTANT;
Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 12:59:25 UTC (rev 10940)
+++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-12-07 13:49:22 UTC (rev 10941)
@@ -77,6 +77,7 @@
"hql/Animal.hbm.xml",
"hql/FooBarCopy.hbm.xml",
"hql/SimpleEntityWithAssociation.hbm.xml",
+ "hql/CrazyIdFieldNames.hbm.xml",
"batchfetch/ProductLine.hbm.xml",
"cid/Customer.hbm.xml",
"cid/Order.hbm.xml",
@@ -94,6 +95,41 @@
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
}
+ public void testCrazyIdFieldNames() {
+ MoreCrazyIdFieldNameStuffEntity top = new MoreCrazyIdFieldNameStuffEntity( "top" );
+ HeresAnotherCrazyIdFieldName next = new HeresAnotherCrazyIdFieldName( "next" );
+ top.setHeresAnotherCrazyIdFieldName( next );
+ MoreCrazyIdFieldNameStuffEntity other = new MoreCrazyIdFieldNameStuffEntity( "other" );
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( next );
+ s.save( top );
+ s.save( other );
+ s.flush();
+
+ List results = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e where e.heresAnotherCrazyIdFieldName is not null" ).list();
+ assertEquals( 1, results.size() );
+ Object result = results.get( 0 );
+ assertClassAssignability( HeresAnotherCrazyIdFieldName.class, result.getClass() );
+ assertSame( next, result );
+
+ results = s.createQuery( "select e.heresAnotherCrazyIdFieldName.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e where e.heresAnotherCrazyIdFieldName is not null" ).list();
+ assertEquals( 1, results.size() );
+ result = results.get( 0 );
+ assertClassAssignability( Long.class, result.getClass() );
+ assertEquals( next.getHeresAnotherCrazyIdFieldName(), result );
+
+ results = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e" ).list();
+ assertEquals( 1, results.size() );
+ Iterator itr = s.createQuery( "select e.heresAnotherCrazyIdFieldName from MoreCrazyIdFieldNameStuffEntity e" ).iterate();
+ assertTrue( itr.hasNext() ); itr.next(); assertFalse( itr.hasNext() );
+
+ s.delete( top );
+ s.delete( next );
+ s.getTransaction().commit();
+ s.close();
+ }
+
public void testImplicitJoinsInDifferentClauses() {
// HHH-2257 :
// both the classic and ast translators output the same syntactically valid sql
Modified: trunk/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml 2006-12-07 12:59:25 UTC (rev 10940)
+++ trunk/Hibernate3/test/org/hibernate/test/hql/CrazyIdFieldNames.hbm.xml 2006-12-07 13:49:22 UTC (rev 10941)
@@ -4,16 +4,16 @@
<hibernate-mapping package="org.hibernate.test.hql">
- <class name="HeresAnotherCrazyIdFieldName">
+ <class name="HeresAnotherCrazyIdFieldName" table="CRAZY_ID_NODE">
<id name="heresAnotherCrazyIdFieldName" column="ID" type="long">
- <generator class="native"/>
+ <generator class="increment"/>
</id>
<property name="name" type="string"/>
</class>
- <class name="MoreCrazyIdFieldNameStuffEntity">
+ <class name="MoreCrazyIdFieldNameStuffEntity" table="CRAZY_ID_TOP">
<id name="moreCrazyIdFieldNameStuffEntity" column="ID" type="long">
- <generator class="native"/>
+ <generator class="increment"/>
</id>
<property name="name" type="string" />
<many-to-one name="heresAnotherCrazyIdFieldName" class="HeresAnotherCrazyIdFieldName"/>
Modified: trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-12-07 12:59:25 UTC (rev 10940)
+++ trunk/Hibernate3/test/org/hibernate/test/hql/HQLTest.java 2006-12-07 13:49:22 UTC (rev 10941)
@@ -43,13 +43,24 @@
public HQLTest(String x) {
super( x );
- SelectClause.VERSION2_SQL = true;
}
protected boolean dropAfterFailure() {
return false;
}
+ protected void setUp() throws Exception {
+ super.setUp();
+ SelectClause.VERSION2_SQL = true;
+ DotNode.REGRESSION_STYLE_JOIN_SUPPRESSION = true;
+ }
+
+ protected void tearDown() throws Exception {
+ SelectClause.VERSION2_SQL = false;
+ DotNode.REGRESSION_STYLE_JOIN_SUPPRESSION = false;
+ super.tearDown();
+ }
+
//FAILING TESTS:
public void testSubComponentReferences() {
17 years, 4 months
Hibernate SVN: r10940 - branches/Branch_3_2/Hibernate3/src/org/hibernate/jdbc
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-12-07 07:59:25 -0500 (Thu, 07 Dec 2006)
New Revision: 10940
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/jdbc/ConnectionManager.java
Log:
bug in borrowed connection releasing
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/jdbc/ConnectionManager.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/jdbc/ConnectionManager.java 2006-12-07 12:59:08 UTC (rev 10939)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/jdbc/ConnectionManager.java 2006-12-07 12:59:25 UTC (rev 10940)
@@ -168,8 +168,12 @@
public void releaseBorrowedConnection() {
if ( borrowedConnection != null ) {
- borrowedConnection = null;
- BorrowedConnectionProxy.renderUnuseable( borrowedConnection );
+ try {
+ BorrowedConnectionProxy.renderUnuseable( borrowedConnection );
+ }
+ finally {
+ borrowedConnection = null;
+ }
}
}
17 years, 4 months