From 33268fe0dd700a17c6639791ba2a941452475840 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 1 May 2013 22:50:34 +0200 Subject: [PATCH] HHH-5465 - HQL left join fetch of an element collection following a left join fetch of a one-to-one relationship causes NullPointerException (testcase) --- .../test/collection/set/hhh8206/Contact.java | 97 +++++++++++++++++++ .../collection/set/hhh8206/EmailAddress.java | 57 +++++++++++ .../JoinFetchElementCollectionTest.java | 61 ++++++++++++ .../test/collection/set/hhh8206/User.java | 87 +++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/Contact.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/EmailAddress.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/JoinFetchElementCollectionTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/User.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/Contact.java b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/Contact.java new file mode 100644 index 0000000000..cb63418055 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/Contact.java @@ -0,0 +1,97 @@ +package org.hibernate.test.collection.set.hhh8206; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Basic; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +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.ManyToMany; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name="contact") +public class Contact implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String name; + private Set emailAddresses = new HashSet(); + private Set emailAddresses2 = new HashSet(); + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Basic + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @ElementCollection + @CollectionTable(name = "user_email_addresses2", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) + public Set getEmailAddresses2() { + return emailAddresses2; + } + + public void setEmailAddresses2(Set emailAddresses2) { + this.emailAddresses2 = emailAddresses2; + } + + @ElementCollection + @CollectionTable(name = "user_email_addresses", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) + public Set getEmailAddresses() { + return emailAddresses; + } + + public void setEmailAddresses(Set emailAddresses) { + this.emailAddresses = emailAddresses; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Contact)) { + return false; + } + final Contact other = (Contact) obj; + if (this.id == null || other.id == null) { + return this == obj; + } + if(!this.id.equals(other.id)) { + return this == obj; + } + return true; + } + + @Override + public String toString() { + return "com.clevercure.web.hibernateissuecache.User[ id=" + id + " ]"; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/EmailAddress.java b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/EmailAddress.java new file mode 100644 index 0000000000..50fcf5a0dc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/EmailAddress.java @@ -0,0 +1,57 @@ +package org.hibernate.test.collection.set.hhh8206; + +import java.io.Serializable; +import java.util.Set; +import javax.persistence.*; + +@Embeddable +public class EmailAddress implements Serializable { + + private static final long serialVersionUID = 1L; + private String email; + + public EmailAddress() { + } + + public EmailAddress(String email) { + this.email = email; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (email != null ? email.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof EmailAddress)) { + return false; + } + final EmailAddress other = (EmailAddress) obj; + if (this.email == null || other.email == null) { + return this == obj; + } + if(!this.email.equals(other.email)) { + return this == obj; + } + return true; + } + + @Override + public String toString() { + return "com.clevercure.web.hibernateissuecache.EmailAddress[ email=" + email + " ]"; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/JoinFetchElementCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/JoinFetchElementCollectionTest.java new file mode 100644 index 0000000000..2870a88517 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/JoinFetchElementCollectionTest.java @@ -0,0 +1,61 @@ +package org.hibernate.test.collection.set.hhh8206; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.Session; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Test; + +public class JoinFetchElementCollectionTest extends BaseCoreFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {Contact.class, EmailAddress.class, User.class}; + } + + @Test + public void test(){ + Set emailAddresses = new HashSet(); + emailAddresses.add(new EmailAddress("test1@test.com")); + emailAddresses.add(new EmailAddress("test2@test.com")); + emailAddresses.add(new EmailAddress("test3@test.com")); + + { + // Session 1: Insert a user with email addresses but no emailAddresses2 + Session session = openSession(); + session.beginTransaction(); + + User user = new User(); + user.setName("john"); + Contact contact = new Contact(); + contact.setName("John Doe"); + contact.setEmailAddresses(emailAddresses); + contact = (Contact) session.merge(contact); + user.setContact(contact); + user = (User) session.merge(user); + + session.getTransaction().commit(); + session.close(); + } + { + // Session 2: Retrieve the user object and check if the sets have the expected values + Session session = openSession(); + session.beginTransaction(); + User user = (User) session.createQuery("SELECT user " + + "FROM User user " + + "LEFT OUTER JOIN FETCH user.contact " + + "LEFT OUTER JOIN FETCH user.contact.emailAddresses2 " + + "LEFT OUTER JOIN FETCH user.contact.emailAddresses") + .uniqueResult(); + session.getTransaction().commit(); + session.close(); + + Assert.assertEquals(emailAddresses, user.getContact().getEmailAddresses()); + Assert.assertTrue(user.getContact().getEmailAddresses2().isEmpty()); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/User.java b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/User.java new file mode 100644 index 0000000000..315195a168 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/set/hhh8206/User.java @@ -0,0 +1,87 @@ +package org.hibernate.test.collection.set.hhh8206; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Basic; +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +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.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name="users") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String name; + private Contact contact; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Basic + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @ManyToOne(optional = true) + @JoinColumn(name = "contact_id", nullable = true, unique = true) + public Contact getContact() { + return contact; + } + + public void setContact(Contact contact) { + this.contact = contact; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof User)) { + return false; + } + final User other = (User) obj; + if (this.id == null || other.id == null) { + return this == obj; + } + if(!this.id.equals(other.id)) { + return this == obj; + } + return true; + } + + @Override + public String toString() { + return "com.clevercure.web.hibernateissuecache.User[ id=" + id + " ]"; + } +}