Author: steve.ebersole(a)jboss.com
Date: 2007-07-31 09:39:23 -0400 (Tue, 31 Jul 2007)
New Revision: 12859
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/MapKey.java
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Mappings.hbm.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Part.java
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Product.java
Modified:
core/trunk/core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/CollectionSuite.java
Log:
HHH-2711 : composite-map-key + unidir map can lead to PropertyAccessException
Modified:
core/trunk/core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java 2007-07-31
01:27:24 UTC (rev 12858)
+++
core/trunk/core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -1,25 +1,25 @@
//$Id: PojoComponentTuplizer.java 9619 2006-03-15 00:12:47Z steve.ebersole(a)jboss.com $
package org.hibernate.tuple.component;
+import java.io.Serializable;
import java.lang.reflect.Method;
-import java.io.Serializable;
+import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
-import org.hibernate.AssertionFailure;
-import org.hibernate.tuple.component.AbstractComponentTuplizer;
-import org.hibernate.tuple.Instantiator;
-import org.hibernate.tuple.PojoInstantiator;
-import org.hibernate.util.ReflectHelper;
+import org.hibernate.bytecode.BasicProxyFactory;
import org.hibernate.bytecode.ReflectionOptimizer;
-import org.hibernate.bytecode.BasicProxyFactory;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property;
+import org.hibernate.property.BackrefPropertyAccessor;
import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
+import org.hibernate.tuple.Instantiator;
+import org.hibernate.tuple.PojoInstantiator;
+import org.hibernate.util.ReflectHelper;
/**
* A {@link ComponentTuplizer} specific to the pojo entity mode.
@@ -76,6 +76,9 @@
}
public Object[] getPropertyValues(Object component) throws HibernateException {
+ if ( component == BackrefPropertyAccessor.UNKNOWN ) {
+ return new Object[ propertySpan ];
+ }
if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
return optimizer.getAccessOptimizer().getPropertyValues( component );
}
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/CollectionSuite.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/CollectionSuite.java 2007-07-31
01:27:24 UTC (rev 12858)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/CollectionSuite.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -9,6 +9,7 @@
import org.hibernate.test.collection.map.PersistentMapTest;
import org.hibernate.test.collection.original.CollectionTest;
import org.hibernate.test.collection.set.PersistentSetTest;
+import org.hibernate.test.collection.backref.map.compkey.BackrefCompositeMapKeyTest;
/**
* Suite of collection (i.e. PersistentCollection) related tests
@@ -25,6 +26,7 @@
suite.addTest( PersistentMapTest.suite() );
suite.addTest( CollectionTest.suite() );
suite.addTest( PersistentSetTest.suite() );
+ suite.addTest( BackrefCompositeMapKeyTest.suite() );
return suite;
}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.test.collection.backref.map.compkey;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.LockMode;
+import org.hibernate.Hibernate;
+import org.hibernate.util.SerializationHelper;
+
+/**
+ * BackrefCompositeMapKeyTest implementation. Test access to a composite map-key
+ * backref via a number of different access methods.
+ *
+ * @author Steve Ebersole
+ */
+public class BackrefCompositeMapKeyTest extends FunctionalTestCase {
+ public BackrefCompositeMapKeyTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "collection/backref/map/compkey/Mappings.hbm.xml" };
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( BackrefCompositeMapKeyTest.class );
+ }
+
+ public void testOrphanDeleteOnDelete() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+ session.flush();
+
+ prod.getParts().remove( mapKey );
+
+ session.delete( prod );
+
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( "Orphan 'Widge' was not deleted", session.get(Part.class,
"Widge") );
+ assertNull( "Orphan 'Get' was not deleted", session.get(Part.class,
"Get") );
+ assertNull( "Orphan 'Widget' was not deleted",
session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteAfterPersist() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+
+ prod.getParts().remove( mapKey );
+
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteAfterPersistAndFlush() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+ session.flush();
+
+ prod.getParts().remove( mapKey );
+
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( session.get(Part.class, "Widge") );
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteAfterLock() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ),part2 );
+ session.persist( prod );
+ t.commit();
+ session.close();
+
+
+ session = openSession();
+ t = session.beginTransaction();
+ session.lock(prod, LockMode.READ);
+ prod.getParts().remove(mapKey);
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( session.get(Part.class, "Widge") );
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteOnSaveOrUpdate() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+ t.commit();
+ session.close();
+
+ prod.getParts().remove( mapKey );
+
+ session = openSession();
+ t = session.beginTransaction();
+ session.saveOrUpdate(prod);
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( session.get(Part.class, "Widge") );
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteOnSaveOrUpdateAfterSerialization() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+ t.commit();
+ session.close();
+
+ prod.getParts().remove( mapKey );
+
+ prod = (Product) SerializationHelper.clone( prod );
+
+ session = openSession();
+ t = session.beginTransaction();
+ session.saveOrUpdate(prod);
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( session.get(Part.class, "Widge") );
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDelete() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey( "Bottom" ), part2 );
+ session.persist( prod );
+ t.commit();
+ session.close();
+
+ getSessions().evict(Product.class);
+ getSessions().evict(Part.class);
+
+ session = openSession();
+ t = session.beginTransaction();
+ prod = (Product) session.get(Product.class, "Widget");
+ assertTrue( Hibernate.isInitialized( prod.getParts() ) );
+ part = (Part) session.get(Part.class, "Widge");
+ prod.getParts().remove(mapKey);
+ t.commit();
+ session.close();
+
+ getSessions().evict(Product.class);
+ getSessions().evict(Part.class);
+
+ session = openSession();
+ t = session.beginTransaction();
+ prod = (Product) session.get(Product.class, "Widget");
+ assertTrue( Hibernate.isInitialized( prod.getParts() ) );
+ assertNull( prod.getParts().get(new MapKey("Top")));
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+
+ public void testOrphanDeleteOnMerge() {
+ Session session = openSession();
+ Transaction t = session.beginTransaction();
+ Product prod = new Product( "Widget" );
+ Part part = new Part( "Widge", "part if a Widget" );
+ MapKey mapKey = new MapKey( "Top" );
+ prod.getParts().put( mapKey, part );
+ Part part2 = new Part( "Get", "another part if a Widget" );
+ prod.getParts().put( new MapKey("Bottom"), part2 );
+ session.persist( prod );
+ t.commit();
+ session.close();
+
+ prod.getParts().remove( mapKey );
+
+ session = openSession();
+ t = session.beginTransaction();
+ session.merge(prod);
+ t.commit();
+ session.close();
+
+ session = openSession();
+ t = session.beginTransaction();
+ assertNull( session.get(Part.class, "Widge") );
+ assertNotNull( session.get(Part.class, "Get") );
+ session.delete( session.get(Product.class, "Widget") );
+ t.commit();
+ session.close();
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/MapKey.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/MapKey.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/MapKey.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.test.collection.backref.map.compkey;
+
+import java.io.Serializable;
+
+/**
+ * A composite map key.
+ *
+ * @author Steve Ebersole
+ */
+public class MapKey implements Serializable {
+ private String role;
+
+ public MapKey() {
+ }
+
+ public MapKey(String role) {
+ this.role = role;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ MapKey mapKey = ( MapKey ) o;
+
+ if ( !role.equals( mapKey.role ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ return role.hashCode();
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Mappings.hbm.xml
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Mappings.hbm.xml
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Mappings.hbm.xml 2007-07-31
13:39:23 UTC (rev 12859)
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!--
+ ~ Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, v. 2.1. This program is distributed in the
+ ~ hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ ~ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ ~ Lesser General Public License for more details. You should have received a
+ ~ copy of the GNU Lesser General Public License, v.2.1 along with this
+ ~ distribution; if not, write to the Free Software Foundation, Inc.,
+ ~ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ~
+ ~ Red Hat Author(s): Steve Ebersole
+ -->
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+ Demonstrates a unidirectional map mapping where the map key is a
+ composite. The unidirectional collection forces Hibernate to use
+ a backref. We want to make sure the backref works properly with
+ the component.
+-->
+<hibernate-mapping
package="org.hibernate.test.collection.backref.map.compkey"
default-access="field">
+
+ <class name="Product" table="t_product">
+ <id name="name"/>
+ <map name="parts" table="Parts"
cascade="all,delete-orphan" fetch="join">
+ <key column="productName" not-null="true"/>
+ <composite-map-key class="MapKey">
+ <key-property name="role"/>
+ </composite-map-key>
+ <one-to-many class="Part"/>
+ </map>
+ </class>
+
+ <class name="Part" table="t_part">
+ <id name="name"/>
+ <property name="description" not-null="true"/>
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Part.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Part.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Part.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.test.collection.backref.map.compkey;
+
+import java.io.Serializable;
+
+/**
+ * Part implementation
+ *
+ * @author Steve Ebersole
+ */
+public class Part implements Serializable {
+ private String name;
+ private String description;
+
+ public Part() {
+ }
+
+ public Part(String name) {
+ this.name = name;
+ }
+
+ public Part(String name, String description) {
+ this.name = name;
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Product.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Product.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/collection/backref/map/compkey/Product.java 2007-07-31
13:39:23 UTC (rev 12859)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.test.collection.backref.map.compkey;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Product implementation
+ *
+ * @author Steve Ebersole
+ */
+public class Product implements Serializable {
+ private String name;
+ private Map parts = new HashMap();
+
+ public Product() {
+ }
+
+ public Product(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Map getParts() {
+ return parts;
+ }
+
+ public void setParts(Map parts) {
+ this.parts = parts;
+ }
+}