From 37b645999c46cf2ece3ed6b7051352ce6dba7919 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 23 Apr 2012 13:27:14 -0500 Subject: [PATCH] HHH-7225 - NullPointerException after persisting null entity value as natural-Id --- .../java/org/hibernate/type/EntityType.java | 9 ++- .../hibernate/test/naturalid/nullable/A.java | 57 +++++++++++++++++++ .../hibernate/test/naturalid/nullable/B.java | 49 ++++++++++++++++ .../nullable/NullableNaturalIdTest.java | 36 +++++++++++- 4 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/A.java create mode 100644 hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/B.java diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index 72e93527d1..d33b3098c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -325,10 +325,13 @@ public abstract class EntityType extends AbstractType implements AssociationType return persister.getIdentifierType().getHashCode( id, factory ); } - /** - * {@inheritDoc} - */ + @Override public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) { + // associations (many-to-one and one-to-one) can be null... + if ( x == null || y == null ) { + return x == y; + } + EntityPersister persister = factory.getEntityPersister(associatedEntityName); if ( !persister.canExtractIdOutOfEntity() ) { return super.isEqual(x, y ); diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/A.java b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/A.java new file mode 100644 index 0000000000..fbe5767a9d --- /dev/null +++ b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/A.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * 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, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY 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 + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.naturalid.nullable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.annotations.NaturalId; + +/** + * @author Guenther Demetz + */ +@Entity +public class A { + @Id + @GeneratedValue(strategy = GenerationType.TABLE) + public long oid; + + @ManyToOne + @NaturalId(mutable=true) + public C assC; + + @Column + @NaturalId(mutable=true) + public String myname; + + @OneToMany(mappedBy="assA") + public Set assB = new HashSet(); +} \ No newline at end of file diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/B.java b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/B.java new file mode 100644 index 0000000000..d7bbc77f85 --- /dev/null +++ b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/B.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * 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, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY 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 + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.naturalid.nullable; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.NaturalId; + +/** + * @author Guenther Demetz + */ +@Entity +public class B { + @Id + @GeneratedValue(strategy = GenerationType.TABLE) + public long oid; + + @ManyToOne + @NaturalId(mutable = true) + public A assA = null; + + @NaturalId(mutable = true) + public int naturalid; +} diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/NullableNaturalIdTest.java b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/NullableNaturalIdTest.java index 250418bda2..d35d152213 100644 --- a/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/NullableNaturalIdTest.java +++ b/hibernate-core/src/matrix/java/org/hibernate/test/naturalid/nullable/NullableNaturalIdTest.java @@ -28,13 +28,16 @@ import org.junit.Test; import org.hibernate.Session; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + /** * @author Steve Ebersole */ public class NullableNaturalIdTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { C.class }; + return new Class[] { A.class, B.class, C.class }; } @Test @@ -53,4 +56,35 @@ public class NullableNaturalIdTest extends BaseCoreFunctionalTestCase { session.getTransaction().commit(); session.close(); } + + @Test + public void testUniqueAssociation() { + Session session = openSession(); + session.beginTransaction(); + A a = new A(); + B b = new B(); + b.naturalid = 100; + session.persist( a ); + session.persist( b ); //b.assA is declared NaturalId, his value is null this moment + b.assA = a; + a.assB.add( b ); + session.getTransaction().commit(); + session.close(); + + session = openSession(); + session.beginTransaction(); + // this is OK + assertNotNull( session.byNaturalId( B.class ).using( "naturalid", 100 ).using( "assA", a ).load() ); + // this fails, cause EntityType.compare(Object x, Object y) always returns 0 ! + assertNull( session.byNaturalId( B.class ).using( "naturalid", 100 ).using( "assA", null ).load() ); + session.getTransaction().commit(); + session.close(); + + session = openSession(); + session.beginTransaction(); + session.delete( b ); + session.delete( a ); + session.getTransaction().commit(); + session.close(); + } }