Author: epbernard
Date: 2007-02-15 01:07:38 -0500 (Thu, 15 Feb 2007)
New Revision: 11208
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadeStyle.java
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadingAction.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/A.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B1.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B2.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B3.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B4.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C1.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C2.java
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/CascadePersistTest.java
Modified:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistOnFlushEventListener.java
Log:
EJB-266 no longer cascade PERSIST on lazy collections (checked over the test suite and the
TCK)
Modified:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java 2007-02-14
19:43:45 UTC (rev 11207)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistEventListener.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -5,7 +5,9 @@
import org.hibernate.event.EventSource;
import org.hibernate.event.def.DefaultPersistEventListener;
-import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.engine.CascadingAction;
+import org.hibernate.engine.EJB3CascadingAction;
+import org.hibernate.engine.EJB3CascadeStyle;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation
@@ -13,6 +15,10 @@
* @author Emmanuel Bernard
*/
public class EJB3PersistEventListener extends DefaultPersistEventListener implements
CallbackHandlerConsumer {
+ static {
+ EJB3CascadeStyle.PERSIST_EJB3.hasOrphanDelete(); //triggers class loading
+ }
+
private EntityCallbackHandler callbackHandler;
public void setCallbackHandler(EntityCallbackHandler callbackHandler) {
@@ -43,4 +49,9 @@
return super.saveWithGeneratedId( entity, entityName, anything, source,
requiresImmediateIdAccess );
}
+
+ @Override
+ protected CascadingAction getCascadeAction() {
+ return EJB3CascadingAction.PERSIST_SKIPLAZY;
+ }
}
Modified:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistOnFlushEventListener.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistOnFlushEventListener.java 2007-02-14
19:43:45 UTC (rev 11207)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/event/EJB3PersistOnFlushEventListener.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -7,6 +7,7 @@
* @author Emmanuel Bernard
*/
public class EJB3PersistOnFlushEventListener extends EJB3PersistEventListener {
+ @Override
protected CascadingAction getCascadeAction() {
return CascadingAction.PERSIST_ON_FLUSH;
}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadeStyle.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadeStyle.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadeStyle.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,32 @@
+//$Id: $
+package org.hibernate.engine;
+
+/**
+ * Becasue CascadeStyle is not opened and package protected,
+ * I need to subclass and override the persist alias
+ *
+ * Note that This class has to be triggered by EJB3PersistEventListener at class loading
time
+ *
+ * TODO get rid of it for 3.3
+ *
+ * @author Emmanuel Bernard
+ */
+public abstract class EJB3CascadeStyle extends CascadeStyle {
+
+ /**
+ * cascade using EJB3CascadingAction
+ */
+ public static final CascadeStyle PERSIST_EJB3 = new CascadeStyle() {
+ public boolean doCascade(CascadingAction action) {
+ return action==EJB3CascadingAction.PERSIST_SKIPLAZY
+ || action==CascadingAction.PERSIST_ON_FLUSH;
+ }
+ public String toString() {
+ return "STYLE_PERSIST_SKIPLAZY";
+ }
+ };
+
+ static {
+ STYLES.put( "persist", PERSIST_EJB3 );
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadingAction.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadingAction.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/engine/EJB3CascadingAction.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,47 @@
+//$Id: $
+package org.hibernate.engine;
+
+import java.util.Map;
+import java.util.Iterator;
+
+import org.hibernate.event.EventSource;
+import org.hibernate.HibernateException;
+import org.hibernate.type.CollectionType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Because of CascadingAction constructor visibility
+ * I need a packaged friendly subclass
+ * TODO Get rid of it for 3.3
+ * @author Emmanuel Bernard
+ */
+public abstract class EJB3CascadingAction extends CascadingAction {
+ private static Log log = LogFactory.getLog( CascadingAction.class );
+ /**
+ * @see org.hibernate.Session#persist(Object)
+ */
+ public static final CascadingAction PERSIST_SKIPLAZY = new CascadingAction() {
+ public void cascade(EventSource session, Object child, String entityName, Object
anything, boolean isCascadeDeleteEnabled)
+ throws HibernateException {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "cascading to persist: " + entityName );
+ }
+ session.persist( entityName, child, (Map) anything );
+ }
+ public Iterator getCascadableChildrenIterator(EventSource session, CollectionType
collectionType, Object collection) {
+ // persists don't cascade to uninitialized collections
+ return CascadingAction.getLoadedElementsIterator( session, collectionType, collection
);
+ }
+ public boolean deleteOrphans() {
+ return false;
+ }
+ public boolean performOnLazyProperty() {
+ return false;
+ }
+ public String toString() {
+ return "ACTION_PERSIST_SKIPLAZY";
+ }
+ };
+
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/A.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/A.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/A.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,92 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+@Entity
+public class A {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ private String name;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "a", cascade =
{CascadeType.PERSIST} )
+ private Set<B1> b1List;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "a", cascade =
{CascadeType.PERSIST} )
+ private Set<B2> b2List;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "a", cascade =
{CascadeType.PERSIST} )
+ private Set<B3> b3List;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "a", cascade =
{CascadeType.PERSIST} )
+ private Set<B4> b4List;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Set<B1> getB1List() {
+ if ( b1List == null )
+ b1List = new HashSet<B1>();
+ return b1List;
+ }
+
+ public void setB1List(Set<B1> list) {
+ b1List = list;
+ }
+
+ public Set<B2> getB2List() {
+ if ( b2List == null )
+ b2List = new HashSet<B2>();
+ return b2List;
+ }
+
+ public void setB2List(Set<B2> list) {
+ b2List = list;
+ }
+
+ public Set<B3> getB3List() {
+ return b3List;
+ }
+
+ public void setB3List(Set<B3> list) {
+ if ( b3List == null )
+ b3List = new HashSet<B3>();
+ b3List = list;
+ }
+
+ public Set<B4> getB4List() {
+ return b4List;
+ }
+
+ public void setB4List(Set<B4> list) {
+ if ( b4List == null )
+ b4List = new HashSet<B4>();
+ b4List = list;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B1.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B1.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B1.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,56 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+
+
+@Entity
+public class B1 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "aId" )
+ private A a;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "b1", cascade =
{CascadeType.PERSIST} )
+ private Set<C1> c1List;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public A getA() {
+ return a;
+ }
+
+ public void setA(A a) {
+ this.a = a;
+ }
+
+ public Set<C1> getC1List() {
+ if ( c1List == null )
+ c1List = new HashSet<C1>();
+ return c1List;
+ }
+
+ public void setC1List(Set<C1> list) {
+ c1List = list;
+ }
+}
\ No newline at end of file
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B2.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B2.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B2.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,55 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+
+@Entity
+public class B2 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "aId" )
+ private A a;
+
+ @OneToMany( fetch = FetchType.LAZY, mappedBy = "b2", cascade =
{CascadeType.PERSIST} )
+ private Set<C2> c2List;
+
+ public A getA() {
+ return a;
+ }
+
+ public void setA(A a) {
+ this.a = a;
+ }
+
+ public Set<C2> getC2List() {
+ if ( c2List == null )
+ c2List = new HashSet<C2>();
+ return c2List;
+ }
+
+ public void setC2List(Set<C2> list) {
+ c2List = list;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B3.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B3.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B3.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,39 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class B3 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "aId" )
+ private A a;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public A getA() {
+ return a;
+ }
+
+ public void setA(A a) {
+ this.a = a;
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B4.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B4.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/B4.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,39 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class B4 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "aId" )
+ private A a;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public A getA() {
+ return a;
+ }
+
+ public void setA(A a) {
+ this.a = a;
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C1.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C1.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C1.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,39 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class C1 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "b1Id" )
+ private B1 b1;
+
+ public B1 getB1() {
+ return b1;
+ }
+
+ public void setB1(B1 b1) {
+ this.b1 = b1;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C2.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C2.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/C2.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,39 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class C2 {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ private int id;
+
+ @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST} )
+ @JoinColumn( name = "b2Id" )
+ private B2 b2;
+
+ public B2 getB2() {
+ return b2;
+ }
+
+ public void setB2(B2 b2) {
+ this.b2 = b2;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
Added:
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/CascadePersistTest.java
===================================================================
---
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/CascadePersistTest.java
(rev 0)
+++
branches/Branch_3_2/HibernateExt/entitymanager/src/test/org/hibernate/ejb/test/emops/cascade/CascadePersistTest.java 2007-02-15
06:07:38 UTC (rev 11208)
@@ -0,0 +1,97 @@
+//$Id: $
+package org.hibernate.ejb.test.emops.cascade;
+
+import javax.persistence.EntityManager;
+
+import org.hibernate.ejb.test.TestCase;
+import org.hibernate.Session;
+import org.hibernate.stat.Statistics;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class CascadePersistTest extends TestCase {
+
+ public void testLazyCollectionsStayLazyOnPersist() throws Exception {
+ EntityManager em = factory.createEntityManager();
+ em.getTransaction().begin();
+ //initialize
+ A a = new A();
+ a.setName( "name1" );
+ em.persist( a );
+ a = new A();
+ a.setName( "name2" );
+ em.persist( a );
+ a = new A();
+ a.setName( "name3" );
+ em.persist( a );
+ em.flush();
+ a = em.find( A.class, 1 );
+ for ( int i = 0; i < 3; i++ ) {
+ B1 b1 = new B1();
+ b1.setA( a );
+ em.persist( b1 );
+ }
+ for ( int i = 0; i < 3; i++ ) {
+ B2 b2 = new B2();
+ b2.setA( a );
+ em.persist( b2 );
+ }
+ for ( int i = 0; i < 3; i++ ) {
+ B3 b3 = new B3();
+ b3.setA( a );
+ em.persist( b3 );
+ }
+ for ( int i = 0; i < 3; i++ ) {
+ B4 b4 = new B4();
+ b4.setA( a );
+ em.persist( b4 );
+ }
+ em.flush();
+ B1 b1 = em.find( B1.class, 1 );
+ for ( int i = 0; i < 2; i++ ) {
+ C1 c1 = new C1();
+ c1.setB1( b1 );
+ em.persist( c1 );
+ }
+ B2 b2 = em.find( B2.class, 1 );
+ for ( int i = 0; i < 4; i++ ) {
+ C2 c2 = new C2();
+ c2.setB2( b2 );
+ em.persist( c2 );
+ }
+ em.flush();
+ em.clear();
+
+ //test
+ a = em.find( A.class, 1 );
+ C2 c2 = new C2();
+ for ( B2 anotherB2 : a.getB2List() ) {
+ if ( anotherB2.getId() == 1 ) {
+ anotherB2.getC2List().add( c2 );
+ c2.setB2( anotherB2 );
+ }
+ }
+ Statistics statistics = ( (Session) em.getDelegate()
).getSessionFactory().getStatistics();
+ statistics.setStatisticsEnabled( true );
+ statistics.clear();
+ em.persist( c2 );
+ long loaded = statistics.getEntityLoadCount();
+ assertEquals( 0, loaded );
+ em.flush();
+ em.getTransaction().rollback();
+ em.close();
+ }
+
+ public Class[] getAnnotatedClasses() {
+ return new Class[]{
+ A.class,
+ B1.class,
+ B2.class,
+ B3.class,
+ B4.class,
+ C1.class,
+ C2.class
+ };
+ }
+}