diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/spaces/QuerySpacesImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/spaces/QuerySpacesImpl.java index e41bcc4660..e4a1c36a64 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/spaces/QuerySpacesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/build/internal/spaces/QuerySpacesImpl.java @@ -38,6 +38,7 @@ import org.hibernate.loader.plan.spi.QuerySpace; import org.hibernate.loader.plan.spi.QuerySpaceUidNotRegisteredException; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.entity.JoinedSubclassEntityPersister; import org.jboss.logging.Logger; @@ -101,11 +102,25 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces { checkQuerySpaceDoesNotExist( uid ); + // as a temporary fix for HHH-8980 and HHH-8830 we circumvent allowing + // inner joins (canJoinsBeRequired) when the persister is part of an + // entity inheritance. + // + // hasSubclasses() is the closest we can come to even knowing if the + // entity is part of a hierarchy. But its enough, since if there are no + // subclasses we cannot have the case where the attribute to join comes from + // a subclass :) + // + // a better long term fix is to expose whether a joined association attribute + // is defined on the class/superClass(es) or on the subClass(es). Attributes + // from the subClass(es) should not be inner joined; it is ok to inner join + // attributes from the class/superClass(es). + final EntityQuerySpaceImpl space = new EntityQuerySpaceImpl( entityPersister, uid, this, - canJoinsBeRequired + canJoinsBeRequired && !entityPersister.getEntityMetamodel().hasSubclasses() ); registerQuerySpace( space ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Contractor.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Contractor.java new file mode 100644 index 0000000000..67f529c53a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Contractor.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, 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.loadplans.process.inheritance; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +/** + * @author Steve Ebersole + */ +@Entity +public class Contractor extends User { + + // illustrates the problematic situation described in HHH-8330 + + @ManyToOne(fetch= FetchType.EAGER) + @JoinColumn(name="reportsTo_id",nullable=false) + Department reportsTo; + + public Contractor(Integer id, Department reportsTo) { + super( id ); + this.reportsTo = reportsTo; + } + + public Contractor() { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Department.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Department.java new file mode 100644 index 0000000000..ae402b4f42 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Department.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, 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.loadplans.process.inheritance; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Steve Ebersole + */ +@Entity +public class Department { + @Id + Integer id; + + public Department(Integer id) { + this.id = id; + } + + public Department() { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Employee.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Employee.java new file mode 100644 index 0000000000..638f7ebd58 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Employee.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, 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.loadplans.process.inheritance; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; + +/** + * @author Steve Ebersole + */ +@Entity +public class Employee extends User { + + // illustrates the problematic situation described in HHH-8980 + + @ManyToOne(optional = false) + Department belongsTo; + + public Employee(Integer id, Department belongsTo) { + super( id ); + this.belongsTo = belongsTo; + } + + public Employee() { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Test.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Test.java new file mode 100644 index 0000000000..396b02bbba --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/Test.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, 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.loadplans.process.inheritance; + +import org.hibernate.Session; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import static org.junit.Assert.assertNotNull; + +/** + * @author Steve Ebersole + */ +public class Test extends BaseCoreFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Department.class, User.class, Employee.class, Contractor.class }; + } + + @org.junit.Test + public void basicTest() { + Session s = openSession(); + s.beginTransaction(); + User user = new User( 2 ); + s.save( user ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + assertNotNull( s.get( User.class, 2 ) ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + s.createQuery( "delete User" ).executeUpdate(); + s.getTransaction().commit(); + s.close(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/User.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/User.java new file mode 100644 index 0000000000..e089e686c2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/process/inheritance/User.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, 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.loadplans.process.inheritance; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; + +/** + * @author Steve Ebersole + */ +@Entity +@Table( name = "`user`" ) +@Inheritance(strategy = InheritanceType.JOINED) +class User { + @Id + Integer id; + + User(Integer id) { + this.id = id; + } + + User() { + } +}