Hibernate SVN: r18176 - jpamodelgen/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-12-08 17:53:55 -0500 (Tue, 08 Dec 2009)
New Revision: 18176
Removed:
jpamodelgen/trunk/issues.txt
Log:
deleted obsolete issues file
Deleted: jpamodelgen/trunk/issues.txt
===================================================================
--- jpamodelgen/trunk/issues.txt 2009-12-08 22:50:06 UTC (rev 18175)
+++ jpamodelgen/trunk/issues.txt 2009-12-08 22:53:55 UTC (rev 18176)
@@ -1,19 +0,0 @@
-
-- Find host for project
-
-- Implement XML overriding of annotation metadata
-
-- Implement access Type rules for XML metadata
-
-- Investigate why it is not possible to use the Filer API to load non class resources, eg
- /META-INF/orm.xml. The API throws a FilerException with the message "Illegal name /META-INF".
- The call is processingEnv.getFiler().getResource((StandardLocation.CLASS_OUTPUT, "/META-INF", "orm.xml" )
- Currently we work around this by using Class.getResourceAsStream()
-
-- Optimize XML parsing by only processing XML files if they have changed since last run (maybe write
- a tmp file against which to compare the last modified time stamp)
-
-- Reduce the amount of logging and make logging configurable using the possibility to pass arguments to
- the processor using -Akey[=value]
-
-- Write IDE specific plugins which allow to cache processing steps
15 years
Hibernate SVN: r18174 - jpamodelgen/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-12-08 17:48:16 -0500 (Tue, 08 Dec 2009)
New Revision: 18174
Modified:
jpamodelgen/trunk/pom.xml
Log:
Changed the repository configuration
Modified: jpamodelgen/trunk/pom.xml
===================================================================
--- jpamodelgen/trunk/pom.xml 2009-12-08 22:47:55 UTC (rev 18173)
+++ jpamodelgen/trunk/pom.xml 2009-12-08 22:48:16 UTC (rev 18174)
@@ -4,7 +4,7 @@
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
- <version>1.0.0.Beta2-SNAPSHOT</version>
+ <version>1.0.0.Beta1-SNAPSHOT</version>
<name>JPA 2 Static-Metamodel Generator</name>
<description>Annotation Processor to generate JPA 2 static metamodel classes</description>
@@ -229,9 +229,10 @@
<distributionManagement>
<repository>
+ <!-- Copy the dist to the local checkout of the JBoss maven2 repo ${maven.repository.root} -->
+ <!-- It is anticipated that ${maven.repository.root} be set in user's settings.xml -->
<id>repository.jboss.org</id>
- <name>JBoss Release Repository</name>
- <url>scm:svn:https://svn.jboss.org/repos/repository.jboss.org/maven2</url>
+ <url>file://${maven.repository.root}</url>
</repository>
<snapshotRepository>
<id>snapshots.jboss.org</id>
15 years
Hibernate SVN: r18173 - jpamodelgen/tags.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-12-08 17:47:55 -0500 (Tue, 08 Dec 2009)
New Revision: 18173
Removed:
jpamodelgen/tags/v1_0_0_Beta1/
Log:
Removed jpamodelgen/tags/v1_0_0_Beta1
15 years
Hibernate SVN: r18171 - jpamodelgen/tags.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-12-08 17:37:11 -0500 (Tue, 08 Dec 2009)
New Revision: 18171
Added:
jpamodelgen/tags/v1_0_0_Beta1/
Log:
[maven-scm] copy for tag v1_0_0_Beta1
Copied: jpamodelgen/tags/v1_0_0_Beta1 (from rev 18170, jpamodelgen/trunk)
15 years
Hibernate SVN: r18169 - core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2009-12-08 16:19:42 -0500 (Tue, 08 Dec 2009)
New Revision: 18169
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java
Log:
HHH-4654 - Criteria quries must support referencing parameters by name
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java 2009-12-08 18:56:15 UTC (rev 18168)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java 2009-12-08 21:19:42 UTC (rev 18169)
@@ -39,6 +39,7 @@
import javax.persistence.criteria.ParameterExpression;
import org.hibernate.ejb.HibernateEntityManagerImplementor;
+import org.hibernate.util.StringHelper;
/**
* Compiles a JPA criteria query into an executable {@link TypedQuery}. Its single contract is the {@link #compile}
@@ -77,7 +78,9 @@
criteriaQueryImpl.validate();
final Map<ParameterExpression<?>,String> explicitParameterMapping = new HashMap<ParameterExpression<?>,String>();
+ final Map<String,ParameterExpression<?>> explicitParameterNameMapping = new HashMap<String,ParameterExpression<?>>();
final List<ImplicitParameterBinding> implicitParameterBindings = new ArrayList<ImplicitParameterBinding>();
+
RenderingContext renderingContext = new RenderingContext() {
private int aliasCount = 0;
private int explicitParameterCount = 0;
@@ -92,6 +95,12 @@
public void registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter, String jpaqlParameterName) {
explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName );
+ if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) {
+ explicitParameterNameMapping.put(
+ criteriaQueryParameter.getName(),
+ criteriaQueryParameter
+ );
+ }
}
public void registerImplicitParameterBinding(ImplicitParameterBinding binding) {
@@ -109,12 +118,13 @@
implicitParameterBinding.bind( jpaqlQuery );
}
- return wrap( jpaqlQuery, explicitParameterMapping );
+ return wrap( jpaqlQuery, explicitParameterMapping, explicitParameterNameMapping );
}
private <X> TypedQuery<X> wrap(
final TypedQuery<X> jpaqlQuery,
- final Map<ParameterExpression<?>, String> explicitParameterMapping) {
+ final Map<ParameterExpression<?>, String> explicitParameterMapping,
+ final Map<String, ParameterExpression<?>> explicitParameterNameMapping) {
return new TypedQuery<X>() {
public List<X> getResultList() {
@@ -130,7 +140,8 @@
}
public TypedQuery<X> setMaxResults(int i) {
- return jpaqlQuery.setMaxResults( i );
+ jpaqlQuery.setMaxResults( i );
+ return this;
}
public int getFirstResult() {
@@ -138,7 +149,8 @@
}
public TypedQuery<X> setFirstResult(int i) {
- return jpaqlQuery.setFirstResult( i );
+ jpaqlQuery.setFirstResult( i );
+ return this;
}
public Map<String, Object> getHints() {
@@ -146,7 +158,8 @@
}
public TypedQuery<X> setHint(String name, Object value) {
- return jpaqlQuery.setHint( name, value);
+ jpaqlQuery.setHint( name, value);
+ return this;
}
public FlushModeType getFlushMode() {
@@ -154,7 +167,8 @@
}
public TypedQuery<X> setFlushMode(FlushModeType flushModeType) {
- return jpaqlQuery.setFlushMode( flushModeType );
+ jpaqlQuery.setFlushMode( flushModeType );
+ return this;
}
public LockModeType getLockMode() {
@@ -162,7 +176,8 @@
}
public TypedQuery<X> setLockMode(LockModeType lockModeType) {
- return jpaqlQuery.setLockMode( lockModeType );
+ jpaqlQuery.setLockMode( lockModeType );
+ return this;
}
@SuppressWarnings({ "unchecked" })
@@ -181,7 +196,8 @@
@SuppressWarnings({ "unchecked" })
public <T> TypedQuery<X> setParameter(Parameter<T> param, T t) {
- return jpaqlQuery.setParameter( mapToNamedParameter( param ), t );
+ jpaqlQuery.setParameter( mapToNamedParameter( param ), t );
+ return this;
}
@SuppressWarnings({ "RedundantCast" })
@@ -193,47 +209,106 @@
@SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar calendar, TemporalType temporalType) {
- return jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType );
+ jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType );
+ return this;
}
@SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(Parameter<Date> param, Date date, TemporalType temporalType) {
- return jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType );
+ jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType );
+ return this;
}
public <T> T unwrap(Class<T> cls) {
return jpaqlQuery.unwrap( cls );
}
+ @SuppressWarnings({ "unchecked" })
+ public Object getParameterValue(String name) {
+ return getParameterValue( resolveExplicitCriteriaParameterName( name ) );
+ }
- // unsupported stuff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private Parameter resolveExplicitCriteriaParameterName(String name) {
+ Parameter parameter = explicitParameterNameMapping.get( name );
+ if ( parameter == null ) {
+ throw new IllegalArgumentException( "Named parameter [" + name + "] not encountered" );
+ }
+ return parameter;
+ }
- public int executeUpdate() {
- throw new IllegalArgumentException( "Criteria queries do not support update queries" );
+ public Parameter<?> getParameter(String name) {
+ return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) );
}
- public TypedQuery<X> setParameter(String s, Object o) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+ @SuppressWarnings({ "unchecked" })
+ public <T> Parameter<T> getParameter(String name, Class<T> type) {
+ Parameter parameter = resolveExplicitCriteriaParameterName( name );
+ if ( type.isAssignableFrom( parameter.getParameterType() ) ) {
+ return (Parameter<T>) parameter;
+ }
+ throw new IllegalArgumentException(
+ "Named parameter [" + name + "] type is not assignanle to request type ["
+ + type.getName() + "]"
+ );
}
- public TypedQuery<X> setParameter(String s, Calendar calendar, TemporalType temporalType) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+ @SuppressWarnings({ "unchecked" })
+ public TypedQuery<X> setParameter(String name, Object value) {
+ setParameter(
+ resolveExplicitCriteriaParameterName( name, value ),
+ value
+ );
+ return this;
}
- public TypedQuery<X> setParameter(String s, Date date, TemporalType temporalType) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+ private Parameter resolveExplicitCriteriaParameterName(String name, Object value) {
+ Parameter parameter = resolveExplicitCriteriaParameterName( name );
+ // todo : is null valid?
+ if ( value != null ) {
+ if ( ! parameter.getParameterType().isInstance( value ) ) {
+ throw new IllegalArgumentException(
+ "Named parameter [" + name + "] type mismatch; expecting ["
+ + parameter.getParameterType().getName() + "], found ["
+ + value.getClass().getName() + "]"
+ );
+ }
+ }
+ return parameter;
}
- public Object getParameterValue(String name) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+ @SuppressWarnings({ "unchecked" })
+ public TypedQuery<X> setParameter(String name, Calendar calendar, TemporalType temporalType) {
+ Parameter parameter = resolveExplicitCriteriaParameterName( name );
+ if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) {
+ throw new IllegalArgumentException(
+ "Named parameter [" + name + "] type mismatch; expecting ["
+ + Calendar.class.getName() + "], found ["
+ + parameter.getParameterType().getName() + "]"
+ );
+ }
+ setParameter( parameter, calendar, temporalType );
+ return this;
}
- public Parameter<?> getParameter(String name) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+ @SuppressWarnings({ "unchecked" })
+ public TypedQuery<X> setParameter(String name, Date date, TemporalType temporalType) {
+ Parameter parameter = resolveExplicitCriteriaParameterName( name );
+ if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) {
+ throw new IllegalArgumentException(
+ "Named parameter [" + name + "] type mismatch; expecting ["
+ + Date.class.getName() + "], found ["
+ + parameter.getParameterType().getName() + "]"
+ );
+ }
+ setParameter( parameter, date, temporalType );
+ return this;
}
- public <T> Parameter<T> getParameter(String name, Class<T> type) {
- throw new IllegalArgumentException( "Criteria queries do not support named parameters" );
+
+ // unsupported stuff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public int executeUpdate() {
+ throw new IllegalArgumentException( "Criteria queries do not support update queries" );
}
public TypedQuery<X> setParameter(int i, Object o) {
15 years
Hibernate SVN: r18168 - core/trunk/core/src/main/java/org/hibernate/engine.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2009-12-08 13:56:15 -0500 (Tue, 08 Dec 2009)
New Revision: 18168
Modified:
core/trunk/core/src/main/java/org/hibernate/engine/Cascade.java
core/trunk/core/src/main/java/org/hibernate/engine/PersistenceContext.java
core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
Log:
HHH-3860 - Cascading performance problems when session contains many entities
Modified: core/trunk/core/src/main/java/org/hibernate/engine/Cascade.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/Cascade.java 2009-12-08 18:55:27 UTC (rev 18167)
+++ core/trunk/core/src/main/java/org/hibernate/engine/Cascade.java 2009-12-08 18:56:15 UTC (rev 18168)
@@ -152,6 +152,7 @@
if ( style.doCascade( action ) ) {
cascadeProperty(
+ parent,
persister.getPropertyValue( parent, i, entityMode ),
types[i],
style,
@@ -180,6 +181,7 @@
* Cascade an action to the child or children
*/
private void cascadeProperty(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
@@ -191,6 +193,7 @@
AssociationType associationType = (AssociationType) type;
if ( cascadeAssociationNow( associationType ) ) {
cascadeAssociation(
+ parent,
child,
type,
style,
@@ -200,7 +203,7 @@
}
}
else if ( type.isComponentType() ) {
- cascadeComponent( child, (AbstractComponentType) type, anything );
+ cascadeComponent( parent, child, (AbstractComponentType) type, anything );
}
}
}
@@ -211,6 +214,7 @@
}
private void cascadeComponent(
+ final Object parent,
final Object child,
final AbstractComponentType componentType,
final Object anything) {
@@ -220,6 +224,7 @@
CascadeStyle componentPropertyStyle = componentType.getCascadeStyle(i);
if ( componentPropertyStyle.doCascade(action) ) {
cascadeProperty(
+ parent,
children[i],
types[i],
componentPropertyStyle,
@@ -231,16 +236,17 @@
}
private void cascadeAssociation(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
final Object anything,
final boolean isCascadeDeleteEnabled) {
if ( type.isEntityType() || type.isAnyType() ) {
- cascadeToOne( child, type, style, anything, isCascadeDeleteEnabled );
+ cascadeToOne( parent, child, type, style, anything, isCascadeDeleteEnabled );
}
else if ( type.isCollectionType() ) {
- cascadeCollection( child, style, anything, (CollectionType) type );
+ cascadeCollection( parent, child, style, anything, (CollectionType) type );
}
}
@@ -248,6 +254,7 @@
* Cascade an action to a collection
*/
private void cascadeCollection(
+ final Object parent,
final Object child,
final CascadeStyle style,
final Object anything,
@@ -264,6 +271,7 @@
//cascade to current collection elements
if ( elemType.isEntityType() || elemType.isAnyType() || elemType.isComponentType() ) {
cascadeCollectionElements(
+ parent,
child,
type,
style,
@@ -280,6 +288,7 @@
* Cascade an action to a to-one association or any type
*/
private void cascadeToOne(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
@@ -289,7 +298,13 @@
? ( (EntityType) type ).getAssociatedEntityName()
: null;
if ( style.reallyDoCascade(action) ) { //not really necessary, but good for consistency...
- action.cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ eventSource.getPersistenceContext().addChildParent(child, parent);
+ try {
+ action.cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ }
+ finally {
+ eventSource.getPersistenceContext().removeChildParent(child);
+ }
}
}
@@ -297,6 +312,7 @@
* Cascade to the collection elements
*/
private void cascadeCollectionElements(
+ final Object parent,
final Object child,
final CollectionType collectionType,
final CascadeStyle style,
@@ -318,6 +334,7 @@
Iterator iter = action.getCascadableChildrenIterator(eventSource, collectionType, child);
while ( iter.hasNext() ) {
cascadeProperty(
+ parent,
iter.next(),
elemType,
style,
Modified: core/trunk/core/src/main/java/org/hibernate/engine/PersistenceContext.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/PersistenceContext.java 2009-12-08 18:55:27 UTC (rev 18167)
+++ core/trunk/core/src/main/java/org/hibernate/engine/PersistenceContext.java 2009-12-08 18:56:15 UTC (rev 18168)
@@ -482,4 +482,17 @@
public void setReadOnly(Object entity, boolean readOnly);
void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId);
+
+ /**
+ * Put child/parent relation to cache for cascading op
+ * @param parent
+ * @param child
+ */
+ public void addChildParent(Object parent, Object child);
+
+ /**
+ * Remove child/parent relation from cache
+ * @param parent
+ */
+ public void removeChildParent(Object child);
}
Modified: core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2009-12-08 18:55:27 UTC (rev 18167)
+++ core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2009-12-08 18:56:15 UTC (rev 18168)
@@ -119,6 +119,10 @@
// yet loaded ... for now, this is purely transient!
private Map unownedCollections;
+ // Parent entities cache by their child for cascading
+ // May be empty or not contains all relation
+ private Map parentsByChild;
+
private int cascading = 0;
private int loadCounter = 0;
private boolean flushing = false;
@@ -147,7 +151,8 @@
collectionEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
collectionsByKey = new HashMap( INIT_COLL_SIZE );
arrayHolders = IdentityMap.instantiate( INIT_COLL_SIZE );
-
+ parentsByChild = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
+
nullifiableEntityKeys = new HashSet();
initTransientState();
@@ -214,6 +219,7 @@
entitiesByKey.clear();
entitiesByUniqueKey.clear();
entityEntries.clear();
+ parentsByChild.clear();
entitySnapshotsByKey.clear();
collectionsByKey.clear();
collectionEntries.clear();
@@ -360,6 +366,8 @@
while ( iter.hasNext() ) {
if ( iter.next()==entity ) iter.remove();
}
+ // Clear all parent cache
+ parentsByChild.clear();
entitySnapshotsByKey.remove(key);
nullifiableEntityKeys.remove(key);
getBatchFetchQueue().removeBatchLoadableEntityKey(key);
@@ -1104,8 +1112,18 @@
final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
final CollectionPersister collectionPersister = session.getFactory().getCollectionPersister( collectionRole );
+ // try cache lookup first
+ Object parent = parentsByChild.get(childEntity);
+ if (parent != null) {
+ if (isFoundInParent(propertyName, childEntity, persister, collectionPersister, parent)) {
+ return getEntry(parent).getId();
+ }
+ else {
+ parentsByChild.remove(childEntity); // remove wrong entry
+ }
+ }
// iterate all the entities currently associated with the persistence context.
- Iterator entities = entityEntries.entrySet().iterator();
+ Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
final Map.Entry me = ( Map.Entry ) entities.next();
final EntityEntry entityEntry = ( EntityEntry ) me.getValue();
@@ -1207,7 +1225,26 @@
.getEntityPersister(entity);
CollectionPersister cp = session.getFactory()
.getCollectionPersister(entity + '.' + property);
- Iterator entities = entityEntries.entrySet().iterator();
+
+ // try cache lookup first
+ Object parent = parentsByChild.get(childEntity);
+ if (parent != null) {
+ Object index = getIndexInParent(property, childEntity, persister, cp, parent);
+
+ if (index==null && mergeMap!=null) {
+ Object unmergedInstance = mergeMap.get(parent);
+ Object unmergedChild = mergeMap.get(childEntity);
+ if ( unmergedInstance!=null && unmergedChild!=null ) {
+ index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
+ }
+ }
+ if (index!=null) {
+ return index;
+ }
+ parentsByChild.remove(childEntity); // remove wrong entry
+ }
+
+ Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
Map.Entry me = (Map.Entry) entities.next();
EntityEntry ee = (EntityEntry) me.getValue();
@@ -1277,6 +1314,7 @@
public void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId) {
Object entity = entitiesByKey.remove( oldKey );
EntityEntry oldEntry = ( EntityEntry ) entityEntries.remove( entity );
+ parentsByChild.clear();
EntityKey newKey = new EntityKey( generatedId, oldEntry.getPersister(), getSession().getEntityMode() );
addEntity( newKey, entity );
@@ -1487,4 +1525,18 @@
return rtn;
}
+
+ /**
+ * @see org.hibernate.engine.PersistenceContext#addChildParent(java.lang.Object, java.lang.Object)
+ */
+ public void addChildParent(Object child, Object parent) {
+ parentsByChild.put(child, parent);
+ }
+
+ /**
+ * @see org.hibernate.engine.PersistenceContext#removeChildParent(java.lang.Object)
+ */
+ public void removeChildParent(Object child) {
+ parentsByChild.remove(child);
+ }
}
15 years
Hibernate SVN: r18167 - core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2009-12-08 13:55:27 -0500 (Tue, 08 Dec 2009)
New Revision: 18167
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/Cascade.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/PersistenceContext.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
Log:
HHH-3860 - Cascading performance problems when session contains many entities
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/Cascade.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/Cascade.java 2009-12-08 16:32:59 UTC (rev 18166)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/Cascade.java 2009-12-08 18:55:27 UTC (rev 18167)
@@ -152,6 +152,7 @@
if ( style.doCascade( action ) ) {
cascadeProperty(
+ parent,
persister.getPropertyValue( parent, i, entityMode ),
types[i],
style,
@@ -180,6 +181,7 @@
* Cascade an action to the child or children
*/
private void cascadeProperty(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
@@ -191,6 +193,7 @@
AssociationType associationType = (AssociationType) type;
if ( cascadeAssociationNow( associationType ) ) {
cascadeAssociation(
+ parent,
child,
type,
style,
@@ -200,7 +203,7 @@
}
}
else if ( type.isComponentType() ) {
- cascadeComponent( child, (AbstractComponentType) type, anything );
+ cascadeComponent( parent, child, (AbstractComponentType) type, anything );
}
}
}
@@ -211,6 +214,7 @@
}
private void cascadeComponent(
+ final Object parent,
final Object child,
final AbstractComponentType componentType,
final Object anything) {
@@ -220,6 +224,7 @@
CascadeStyle componentPropertyStyle = componentType.getCascadeStyle(i);
if ( componentPropertyStyle.doCascade(action) ) {
cascadeProperty(
+ parent,
children[i],
types[i],
componentPropertyStyle,
@@ -231,16 +236,17 @@
}
private void cascadeAssociation(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
final Object anything,
final boolean isCascadeDeleteEnabled) {
if ( type.isEntityType() || type.isAnyType() ) {
- cascadeToOne( child, type, style, anything, isCascadeDeleteEnabled );
+ cascadeToOne( parent, child, type, style, anything, isCascadeDeleteEnabled );
}
else if ( type.isCollectionType() ) {
- cascadeCollection( child, style, anything, (CollectionType) type );
+ cascadeCollection( parent, child, style, anything, (CollectionType) type );
}
}
@@ -248,6 +254,7 @@
* Cascade an action to a collection
*/
private void cascadeCollection(
+ final Object parent,
final Object child,
final CascadeStyle style,
final Object anything,
@@ -264,6 +271,7 @@
//cascade to current collection elements
if ( elemType.isEntityType() || elemType.isAnyType() || elemType.isComponentType() ) {
cascadeCollectionElements(
+ parent,
child,
type,
style,
@@ -280,6 +288,7 @@
* Cascade an action to a to-one association or any type
*/
private void cascadeToOne(
+ final Object parent,
final Object child,
final Type type,
final CascadeStyle style,
@@ -289,7 +298,13 @@
? ( (EntityType) type ).getAssociatedEntityName()
: null;
if ( style.reallyDoCascade(action) ) { //not really necessary, but good for consistency...
- action.cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ eventSource.getPersistenceContext().addChildParent(child, parent);
+ try {
+ action.cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled);
+ }
+ finally {
+ eventSource.getPersistenceContext().removeChildParent(child);
+ }
}
}
@@ -297,6 +312,7 @@
* Cascade to the collection elements
*/
private void cascadeCollectionElements(
+ final Object parent,
final Object child,
final CollectionType collectionType,
final CascadeStyle style,
@@ -318,6 +334,7 @@
Iterator iter = action.getCascadableChildrenIterator(eventSource, collectionType, child);
while ( iter.hasNext() ) {
cascadeProperty(
+ parent,
iter.next(),
elemType,
style,
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/PersistenceContext.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/PersistenceContext.java 2009-12-08 16:32:59 UTC (rev 18166)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/PersistenceContext.java 2009-12-08 18:55:27 UTC (rev 18167)
@@ -482,4 +482,17 @@
public void setReadOnly(Object entity, boolean readOnly);
void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId);
+
+ /**
+ * Put child/parent relation to cache for cascading op
+ * @param parent
+ * @param child
+ */
+ public void addChildParent(Object parent, Object child);
+
+ /**
+ * Remove child/parent relation from cache
+ * @param parent
+ */
+ public void removeChildParent(Object child);
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2009-12-08 16:32:59 UTC (rev 18166)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java 2009-12-08 18:55:27 UTC (rev 18167)
@@ -119,6 +119,10 @@
// yet loaded ... for now, this is purely transient!
private Map unownedCollections;
+ // Parent entities cache by their child for cascading
+ // May be empty or not contains all relation
+ private Map parentsByChild;
+
private int cascading = 0;
private int loadCounter = 0;
private boolean flushing = false;
@@ -147,7 +151,8 @@
collectionEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
collectionsByKey = new HashMap( INIT_COLL_SIZE );
arrayHolders = IdentityMap.instantiate( INIT_COLL_SIZE );
-
+ parentsByChild = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
+
nullifiableEntityKeys = new HashSet();
initTransientState();
@@ -214,6 +219,7 @@
entitiesByKey.clear();
entitiesByUniqueKey.clear();
entityEntries.clear();
+ parentsByChild.clear();
entitySnapshotsByKey.clear();
collectionsByKey.clear();
collectionEntries.clear();
@@ -360,6 +366,8 @@
while ( iter.hasNext() ) {
if ( iter.next()==entity ) iter.remove();
}
+ // Clear all parent cache
+ parentsByChild.clear();
entitySnapshotsByKey.remove(key);
nullifiableEntityKeys.remove(key);
getBatchFetchQueue().removeBatchLoadableEntityKey(key);
@@ -1100,8 +1108,18 @@
final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
final CollectionPersister collectionPersister = session.getFactory().getCollectionPersister( collectionRole );
+ // try cache lookup first
+ Object parent = parentsByChild.get(childEntity);
+ if (parent != null) {
+ if (isFoundInParent(propertyName, childEntity, persister, collectionPersister, parent)) {
+ return getEntry(parent).getId();
+ }
+ else {
+ parentsByChild.remove(childEntity); // remove wrong entry
+ }
+ }
// iterate all the entities currently associated with the persistence context.
- Iterator entities = entityEntries.entrySet().iterator();
+ Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
final Map.Entry me = ( Map.Entry ) entities.next();
final EntityEntry entityEntry = ( EntityEntry ) me.getValue();
@@ -1203,7 +1221,26 @@
.getEntityPersister(entity);
CollectionPersister cp = session.getFactory()
.getCollectionPersister(entity + '.' + property);
- Iterator entities = entityEntries.entrySet().iterator();
+
+ // try cache lookup first
+ Object parent = parentsByChild.get(childEntity);
+ if (parent != null) {
+ Object index = getIndexInParent(property, childEntity, persister, cp, parent);
+
+ if (index==null && mergeMap!=null) {
+ Object unmergedInstance = mergeMap.get(parent);
+ Object unmergedChild = mergeMap.get(childEntity);
+ if ( unmergedInstance!=null && unmergedChild!=null ) {
+ index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
+ }
+ }
+ if (index!=null) {
+ return index;
+ }
+ parentsByChild.remove(childEntity); // remove wrong entry
+ }
+
+ Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
Map.Entry me = (Map.Entry) entities.next();
EntityEntry ee = (EntityEntry) me.getValue();
@@ -1273,6 +1310,7 @@
public void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId) {
Object entity = entitiesByKey.remove( oldKey );
EntityEntry oldEntry = ( EntityEntry ) entityEntries.remove( entity );
+ parentsByChild.clear();
EntityKey newKey = new EntityKey( generatedId, oldEntry.getPersister(), getSession().getEntityMode() );
addEntity( newKey, entity );
@@ -1483,4 +1521,18 @@
return rtn;
}
+
+ /**
+ * @see org.hibernate.engine.PersistenceContext#addChildParent(java.lang.Object, java.lang.Object)
+ */
+ public void addChildParent(Object child, Object parent) {
+ parentsByChild.put(child, parent);
+ }
+
+ /**
+ * @see org.hibernate.engine.PersistenceContext#removeChildParent(java.lang.Object)
+ */
+ public void removeChildParent(Object child) {
+ parentsByChild.remove(child);
+ }
}
15 years