From: <hib...@li...> - 2006-06-09 17:47:56
|
Author: ste...@jb... Date: 2006-06-09 13:46:51 -0400 (Fri, 09 Jun 2006) New Revision: 10008 Added: trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ChildAssigned.java trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentAssigned.java Modified: trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/CascadeTest.java trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentChild.hbm.xml Log: persist() with non-cascaded associations to transient objects with assigned identifier strategies Modified: trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-06-09 17:46:51 UTC (rev 10008) @@ -210,16 +210,18 @@ return null; } else { - Serializable id = session.getContextEntityIdentifier(object); - if ( id==null ) { - if ( isTransient(entityName, object, Boolean.FALSE, session) ) { + Serializable id = session.getContextEntityIdentifier( object ); + if ( id == null ) { + // context-entity-identifier returns null explicitly if the entity + // is not associated with the persistence context; so make some + // deeper checks... + if ( isTransient(entityName, object, null, session) ) { throw new TransientObjectException( "object references an unsaved transient instance - save the transient instance before flushing: " + entityName == null ? session.guessEntityName( object ) : entityName ); } - id = session.getEntityPersister(entityName, object) - .getIdentifier( object, session.getEntityMode() ); + id = session.getEntityPersister( entityName, object ).getIdentifier( object, session.getEntityMode() ); } return id; } Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java 2006-06-09 17:46:51 UTC (rev 10008) @@ -19,6 +19,7 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.QueryException; +import org.hibernate.TransientObjectException; import org.hibernate.cache.CacheConcurrencyStrategy; import org.hibernate.cache.CacheException; import org.hibernate.cache.entry.CacheEntryStructure; @@ -33,6 +34,7 @@ import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SubselectFetch; +import org.hibernate.engine.ForeignKeys; import org.hibernate.exception.JDBCExceptionHelper; import org.hibernate.exception.SQLExceptionConverter; import org.hibernate.id.IdentifierGenerator; @@ -1582,6 +1584,9 @@ rs.close(); } } + catch( TransientObjectException e ) { + return false; + } finally { session.getBatcher().closeStatement( st ); } Modified: trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/CascadeTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/CascadeTest.java 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/CascadeTest.java 2006-06-09 17:46:51 UTC (rev 10008) @@ -2,8 +2,11 @@ import org.hibernate.test.jpa.AbstractJPATest; import org.hibernate.Session; +import org.hibernate.TransientObjectException; import org.hibernate.event.def.DefaultPersistOnFlushEventListener; import org.hibernate.cfg.Configuration; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * todo: describe CascadeTest @@ -11,6 +14,9 @@ * @author Steve Ebersole */ public class CascadeTest extends AbstractJPATest { + + public static final Log log = LogFactory.getLog( CascadeTest.class ); + public CascadeTest(String name) { super( name ); } @@ -37,7 +43,14 @@ Child c = new Child( "c1" ); c.setParent( p ); s.persist( c ); - s.getTransaction().commit(); + try { + s.getTransaction().commit(); + fail( "expecting TransientObjectException on flush" ); + } + catch( TransientObjectException e ) { + // expected result + log.trace( "handled expected exception", e ); + } s.close(); s = openSession(); @@ -47,4 +60,26 @@ s.getTransaction().commit(); s.close(); } + + public void testPersistOnFlushWithNoCascadeToTransientAssociationWithAssignedIdentifier() { + // according to the JPA spec, persist()ing an entity should throw + // an exception when said entity contains a reference to a transient + // asoociation where that association is not marked for cascading + // the persist operation... + Session s = openSession(); + s.beginTransaction(); + ParentAssigned p = new ParentAssigned( new Long( 1 ), "p1" ); + ChildAssigned c = new ChildAssigned( new Long( 2 ), "c1" ); + c.setParent( p ); + s.persist( c ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + s.createQuery( "delete ChildAssigned" ).executeUpdate(); + s.createQuery( "delete ParentAssigned" ).executeUpdate(); + s.getTransaction().commit(); + s.close(); + } } Added: trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ChildAssigned.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ChildAssigned.java 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ChildAssigned.java 2006-06-09 17:46:51 UTC (rev 10008) @@ -0,0 +1,40 @@ +package org.hibernate.test.jpa.cascade; + +/** + * Child, but with an assigned identifier. + * + * @author Steve Ebersole + */ +public class ChildAssigned { + private Long id; + private String name; + private ParentAssigned parent; + + public ChildAssigned() { + } + + public ChildAssigned(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ParentAssigned getParent() { + return parent; + } + + public void setParent(ParentAssigned parent) { + this.parent = parent; + } +} Added: trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentAssigned.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentAssigned.java 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentAssigned.java 2006-06-09 17:46:51 UTC (rev 10008) @@ -0,0 +1,31 @@ +package org.hibernate.test.jpa.cascade; + +/** + * Parent, but with an assigned identifier. + * + * @author Steve Ebersole + */ +public class ParentAssigned { + private Long id; + private String name; + + public ParentAssigned() { + } + + public ParentAssigned(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} Modified: trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentChild.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentChild.hbm.xml 2006-06-09 17:44:51 UTC (rev 10007) +++ trunk/Hibernate3/test/org/hibernate/test/jpa/cascade/ParentChild.hbm.xml 2006-06-09 17:46:51 UTC (rev 10008) @@ -2,7 +2,7 @@ "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> -<hibernate-mapping package="org.hibernate.test.jpa.cascade"> +<hibernate-mapping package="org.hibernate.test.jpa.cascade" default-access="field"> <class name="Parent" table="PARENT"> <id name="id" column="ID" type="long"> @@ -19,4 +19,19 @@ <many-to-one name="parent" class="Parent" cascade="none"/> </class> + <class name="ParentAssigned" table="PARENT"> + <id name="id" column="ID" type="long"> + <generator class="assigned"/> + </id> + <property name="name"/> + </class> + + <class name="ChildAssigned" table="CHILD"> + <id name="id" column="ID" type="long"> + <generator class="assigned"/> + </id> + <property name="name"/> + <many-to-one name="parent" class="ParentAssigned" cascade="none"/> + </class> + </hibernate-mapping> \ No newline at end of file |