From 75706dafda00c39c889ae33ce58d1f0ca33689a0 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Tue, 29 Jul 2014 16:54:18 -0700 Subject: [PATCH] HHH-9305 : HQL FromElement is not reused in some cases resulting in an additional join (cherry picked from commit a0663f0d6c4185893dbcc2aec4f5fa28ddc8eb35) --- .../hql/internal/ast/tree/DotNode.java | 26 +- .../test/hql/ASTParserLoadingTest.java | 387 ++++++++++++++++++ .../org/hibernate/test/hql/Department.java | 58 +++ .../java/org/hibernate/test/hql/Employee.java | 107 +++++ .../java/org/hibernate/test/hql/Title.java | 61 +++ 5 files changed, 632 insertions(+), 7 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/Department.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/Employee.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/Title.java diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java index 97d3ff937c..2e24b07568 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java @@ -475,10 +475,8 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec /////////////////////////////////////////////////////////////////////////////// boolean found = elem != null; - // even though we might find a pre-existing element by join path, for FromElements originating in a from-clause - // we should only ever use the found element if the aliases match (null != null here). Implied joins are - // always (?) ok to reuse. - boolean useFoundFromElement = found && ( elem.isImplied() || areSame( classAlias, elem.getClassAlias() ) ); + // even though we might find a pre-existing element by join path, we may not be able to reuse it... + boolean useFoundFromElement = found && canReuse( elem, classAlias ); if ( !useFoundFromElement ) { // If this is an implied join in a from element, then use the impled join type which is part of the @@ -527,9 +525,23 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec setFromElement( elem ); // This 'dot' expression now refers to the resulting from element. } - private boolean areSame(String alias1, String alias2) { - // again, null != null here - return !StringHelper.isEmpty( alias1 ) && !StringHelper.isEmpty( alias2 ) && alias1.equals( alias2 ); + private boolean canReuse(FromElement fromElement, String requestedAlias) { + // implicit joins are always(?) ok to reuse + if ( isImplicitJoin( fromElement ) ) { + return true; + } + + // if the from-clauses are the same, we can be a little more aggressive in terms of what we reuse + if ( fromElement.getFromClause() == getWalker().getCurrentFromClause() ) { + return true; + } + + // otherwise (subquery case) dont reuse the fromElement if we are processing the from-clause of the subquery + return getWalker().getCurrentClauseType() != SqlTokenTypes.FROM; + } + + private boolean isImplicitJoin(FromElement fromElement) { + return fromElement.isImplied(); } private void setImpliedJoin(FromElement elem) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java index 1daf0664f1..8618a382d9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java @@ -145,6 +145,14 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { "legacy/Marelo.hbm.xml" }; } + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Department.class, + Employee.class, + Title.class + }; + } @Override public void configure(Configuration cfg) { @@ -1025,6 +1033,145 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { s.close(); } + @Test + @TestForIssue( jiraKey = "HHH-9305") + public void testExplicitToOneInnerJoin() { + final Employee employee1 = new Employee(); + employee1.setFirstName( "Jane" ); + employee1.setLastName( "Doe" ); + final Title title1 = new Title(); + title1.setDescription( "Jane's description" ); + final Department dept1 = new Department(); + dept1.setDeptName( "Jane's department" ); + employee1.setTitle( title1 ); + employee1.setDepartment( dept1 ); + + final Employee employee2 = new Employee(); + employee2.setFirstName( "John" ); + employee2.setLastName( "Doe" ); + final Title title2 = new Title(); + title2.setDescription( "John's title" ); + employee2.setTitle( title2 ); + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( title1 ); + s.persist( dept1 ); + s.persist( employee1 ); + s.persist( title2 ); + s.persist( employee2 ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + Department department = (Department) s.createQuery( "select e.department from Employee e inner join e.department" ).uniqueResult(); + assertEquals( employee1.getDepartment().getDeptName(), department.getDeptName() ); + s.delete( employee1 ); + s.delete( title1 ); + s.delete( department ); + s.delete( employee2 ); + s.delete( title2 ); + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testExplicitToOneOuterJoin() { + final Employee employee1 = new Employee(); + employee1.setFirstName( "Jane" ); + employee1.setLastName( "Doe" ); + final Title title1 = new Title(); + title1.setDescription( "Jane's description" ); + final Department dept1 = new Department(); + dept1.setDeptName( "Jane's department" ); + employee1.setTitle( title1 ); + employee1.setDepartment( dept1 ); + + final Employee employee2 = new Employee(); + employee2.setFirstName( "John" ); + employee2.setLastName( "Doe" ); + final Title title2 = new Title(); + title2.setDescription( "John's title" ); + employee2.setTitle( title2 ); + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( title1 ); + s.persist( dept1 ); + s.persist( employee1 ); + s.persist( title2 ); + s.persist( employee2 ); + s.getTransaction().commit(); + s.close(); + s = openSession(); + s.getTransaction().begin(); + List list = s.createQuery( "select e.department from Employee e left join e.department" ).list(); + assertEquals( 2, list.size() ); + final Department dept; + if ( list.get( 0 ) == null ) { + dept = (Department) list.get( 1 ); + } + else { + dept = (Department) list.get( 0 ); + assertNull( list.get( 1 ) ); + } + assertEquals( dept1.getDeptName(), dept.getDeptName() ); + s.delete( employee1 ); + s.delete( title1 ); + s.delete( dept ); + s.delete( employee2 ); + s.delete( title2 ); + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testExplicitToOneInnerJoinAndImplicitToOne() { + final Employee employee1 = new Employee(); + employee1.setFirstName( "Jane" ); + employee1.setLastName( "Doe" ); + final Title title1 = new Title(); + title1.setDescription( "Jane's description" ); + final Department dept1 = new Department(); + dept1.setDeptName( "Jane's department" ); + employee1.setTitle( title1 ); + employee1.setDepartment( dept1 ); + + final Employee employee2 = new Employee(); + employee2.setFirstName( "John" ); + employee2.setLastName( "Doe" ); + final Title title2 = new Title(); + title2.setDescription( "John's title" ); + employee2.setTitle( title2 ); + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( title1 ); + s.persist( dept1 ); + s.persist( employee1 ); + s.persist( title2 ); + s.persist( employee2 ); + s.getTransaction().commit(); + s.close(); + s = openSession(); + s.getTransaction().begin(); + Object[] result = (Object[]) s.createQuery( + "select e.firstName, e.lastName, e.title.description, e.department from Employee e inner join e.department" + ).uniqueResult(); + assertEquals( employee1.getFirstName(), result[0] ); + assertEquals( employee1.getLastName(), result[1] ); + assertEquals( employee1.getTitle().getDescription(), result[2] ); + assertEquals( employee1.getDepartment().getDeptName(), ( (Department) result[3] ).getDeptName() ); + s.delete( employee1 ); + s.delete( title1 ); + s.delete( result[3] ); + s.delete( employee2 ); + s.delete( title2 ); + s.getTransaction().commit(); + s.close(); + } + @Test public void testNestedComponentIsNull() { // (1) From MapTest originally... @@ -1692,6 +1839,134 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { s.close(); } + @Test + @TestForIssue( jiraKey = "HHH-9305") + @SuppressWarnings( {"unchecked"}) + public void testSelectClauseImplicitJoinOrderByJoinedProperty() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + Zoo zoo = new Zoo(); + zoo.setName("The Zoo"); + zoo.setMammals( new HashMap() ); + zoo.setAnimals( new HashMap() ); + Mammal plat = new Mammal(); + plat.setBodyWeight( 11f ); + plat.setDescription( "Platypus" ); + plat.setZoo( zoo ); + plat.setSerialNumber( "plat123" ); + zoo.getMammals().put( "Platypus", plat ); + zoo.getAnimals().put("plat123", plat); + Zoo otherZoo = new Zoo(); + otherZoo.setName("The Other Zoo"); + otherZoo.setMammals( new HashMap() ); + otherZoo.setAnimals( new HashMap() ); + Mammal zebra = new Mammal(); + zebra.setBodyWeight( 110f ); + zebra.setDescription( "Zebra" ); + zebra.setZoo( otherZoo ); + zebra.setSerialNumber( "zebra123" ); + otherZoo.getMammals().put( "Zebra", zebra ); + otherZoo.getAnimals().put("zebra123", zebra); + Mammal elephant = new Mammal(); + elephant.setBodyWeight( 550f ); + elephant.setDescription( "Elephant" ); + elephant.setZoo( otherZoo ); + elephant.setSerialNumber( "elephant123" ); + otherZoo.getMammals().put( "Elephant", elephant ); + otherZoo.getAnimals().put( "elephant123", elephant ); + s.persist( plat ); + s.persist(zoo); + s.persist( zebra ); + s.persist( elephant ); + s.persist( otherZoo ); + s.flush(); + s.clear(); + Query q = s.createQuery("select a.zoo from Animal a where a.zoo is not null order by a.zoo.name"); + Type type = q.getReturnTypes()[0]; + assertTrue( type instanceof ManyToOneType ); + assertEquals( ( (ManyToOneType) type ).getAssociatedEntityName(), "org.hibernate.test.hql.Zoo" ); + List zoos = (List) q.list(); + assertEquals( 3, zoos.size() ); + assertEquals( otherZoo.getName(), zoos.get( 0 ).getName() ); + assertEquals( 2, zoos.get( 0 ).getMammals().size() ); + assertEquals( 2, zoos.get( 0 ).getAnimals().size() ); + assertSame( zoos.get( 0 ), zoos.get( 1 ) ); + assertEquals( zoo.getName(), zoos.get( 2 ).getName() ); + assertEquals( 1, zoos.get( 2 ).getMammals().size() ); + assertEquals( 1, zoos.get( 2 ).getAnimals().size() ); + s.clear(); + s.delete(plat); + s.delete( zebra ); + s.delete( elephant ); + s.delete(zoo); + s.delete( otherZoo ); + t.commit(); + s.close(); + } + + @Test + @SuppressWarnings( {"unchecked"}) + public void testSelectClauseDistinctImplicitJoinOrderByJoinedProperty() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + Zoo zoo = new Zoo(); + zoo.setName("The Zoo"); + zoo.setMammals( new HashMap() ); + zoo.setAnimals( new HashMap() ); + Mammal plat = new Mammal(); + plat.setBodyWeight( 11f ); + plat.setDescription( "Platypus" ); + plat.setZoo( zoo ); + plat.setSerialNumber( "plat123" ); + zoo.getMammals().put( "Platypus", plat ); + zoo.getAnimals().put("plat123", plat); + Zoo otherZoo = new Zoo(); + otherZoo.setName("The Other Zoo"); + otherZoo.setMammals( new HashMap() ); + otherZoo.setAnimals( new HashMap() ); + Mammal zebra = new Mammal(); + zebra.setBodyWeight( 110f ); + zebra.setDescription( "Zebra" ); + zebra.setZoo( otherZoo ); + zebra.setSerialNumber( "zebra123" ); + otherZoo.getMammals().put( "Zebra", zebra ); + otherZoo.getAnimals().put("zebra123", zebra); + Mammal elephant = new Mammal(); + elephant.setBodyWeight( 550f ); + elephant.setDescription( "Elephant" ); + elephant.setZoo( otherZoo ); + elephant.setSerialNumber( "elephant123" ); + otherZoo.getMammals().put( "Elephant", elephant ); + otherZoo.getAnimals().put( "elephant123", elephant ); + s.persist( plat ); + s.persist(zoo); + s.persist( zebra ); + s.persist( elephant ); + s.persist( otherZoo ); + s.flush(); + s.clear(); + Query q = s.createQuery("select distinct a.zoo from Animal a where a.zoo is not null order by a.zoo.name"); + Type type = q.getReturnTypes()[0]; + assertTrue( type instanceof ManyToOneType ); + assertEquals( ( (ManyToOneType) type ).getAssociatedEntityName(), "org.hibernate.test.hql.Zoo" ); + List zoos = (List) q.list(); + assertEquals( 2, zoos.size() ); + assertEquals( otherZoo.getName(), zoos.get( 0 ).getName() ); + assertEquals( 2, zoos.get( 0 ).getMammals().size() ); + assertEquals( 2, zoos.get( 0 ).getAnimals().size() ); + assertEquals( zoo.getName(), zoos.get( 1 ).getName() ); + assertEquals( 1, zoos.get( 1 ).getMammals().size() ); + assertEquals( 1, zoos.get( 1 ).getAnimals().size() ); + s.clear(); + s.delete(plat); + s.delete( zebra ); + s.delete( elephant ); + s.delete(zoo); + s.delete( otherZoo ); + t.commit(); + s.close(); + } + @Test @SuppressWarnings( {"unchecked"}) public void testSelectClauseImplicitJoinWithIterate() { @@ -2809,6 +3084,118 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase { destroyTestBaseData(); } + @Test + @TestForIssue( jiraKey = "HHH-9305") + public void testDynamicInstantiationWithToOneQueries() throws Exception { + final Employee employee1 = new Employee(); + employee1.setFirstName( "Jane" ); + employee1.setLastName( "Doe" ); + final Title title1 = new Title(); + title1.setDescription( "Jane's description" ); + final Department dept1 = new Department(); + dept1.setDeptName( "Jane's department" ); + employee1.setTitle( title1 ); + employee1.setDepartment( dept1 ); + + final Employee employee2 = new Employee(); + employee2.setFirstName( "John" ); + employee2.setLastName( "Doe" ); + final Title title2 = new Title(); + title2.setDescription( "John's title" ); + employee2.setTitle( title2 ); + + Session s = openSession(); + s.getTransaction().begin(); + s.persist( title1 ); + s.persist( dept1 ); + s.persist( employee1 ); + s.persist( title2 ); + s.persist( employee2 ); + s.getTransaction().commit(); + s.close(); + + // There are 2 to-one associations: Employee.title and Employee.department. + // It appears that adding an explicit join for one of these to-one associations keeps ANSI joins + // at the beginning of the FROM clause, avoiding failures on DBs that cannot handle cross joins + // interleaved with ANSI joins (e.g., PostgreSql). + + s = openSession(); + s.getTransaction().begin(); + List results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e inner join e.title" + ).list(); + assertEquals( "Incorrect result size", 1, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, t.id, t.description, e.department, e.firstName) from Employee e inner join e.title t" + ).list(); + assertEquals( "Incorrect result size", 1, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e inner join e.department" + ).list(); + assertEquals( "Incorrect result size", 1, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, d, e.firstName) from Employee e inner join e.department d" + ).list(); + assertEquals( "Incorrect result size", 1, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e left outer join e.department" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, d, e.firstName) from Employee e left outer join e.department d" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e left outer join e.department inner join e.title" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, t.id, t.description, d, e.firstName) from Employee e left outer join e.department d inner join e.title t" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e left outer join e.department left outer join e.title" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, t.id, t.description, d, e.firstName) from Employee e left outer join e.department d left outer join e.title t" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e left outer join e.department order by e.title.description" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + results = session.createQuery( + "select new Employee(e.id, e.lastName, e.title.id, e.title.description, e.department, e.firstName) from Employee e left outer join e.department d order by e.title.description" + ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertClassAssignability( results.get( 0 ).getClass(), Employee.class ); + s.getTransaction().commit(); + + s.close(); + + s = openSession(); + s.getTransaction().begin(); + s.delete( employee1 ); + s.delete( title1 ); + s.delete( dept1 ); + s.delete( employee2 ); + s.delete( title2 ); + s.getTransaction().commit(); + s.close(); + } + @Test @SuppressWarnings( {"UnusedAssignment"}) public void testCachedJoinedAndJoinFetchedManyToOne() throws Exception { diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Department.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Department.java new file mode 100644 index 0000000000..491e7d8d45 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Department.java @@ -0,0 +1,58 @@ +/* + * 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.hql; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="department") +public class Department implements java.io.Serializable { + private Integer deptNo; + private String deptName; + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id_dep") + public Integer getDeptNo() { + return this.deptNo; + } + + public void setDeptNo(Integer deptNo) { + this.deptNo = deptNo; + } + + public String getDeptName() { + return this.deptName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Employee.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Employee.java new file mode 100644 index 0000000000..b3e689a2ca --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Employee.java @@ -0,0 +1,107 @@ +/* + * 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.hql; + +import java.io.Serializable; + +import javax.persistence.Column; +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.ManyToOne; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +@Entity +@Table(name="employee") +public class Employee implements Serializable { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id_emp") + private Integer id; + + private String firstName; + private String lastName; + + @OneToOne + @JoinColumn(name="id_title") + private Title title; + + @ManyToOne(fetch=FetchType.LAZY) + @JoinColumn(name="id_depto") + private Department department; + + public Employee() {} + + public Employee(Integer _id, String _lastName, Integer _idTitle, String _descriptionTitle, Department _dept, String _fname) { + setId(_id); + setLastName(_lastName); + Title _title = new Title(); + _title.setId(_idTitle); + _title.setDescription(_descriptionTitle); + setTitle(_title); + setDepartment(_dept); + setFirstName(_fname); + } + + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public Title getTitle() { + return title; + } + public void setTitle(Title title) { + this.title = title; + } + public Department getDepartment() { + return department; + } + public void setDepartment(Department department) { + this.department = department; + } + + + + + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Title.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Title.java new file mode 100644 index 0000000000..146ab438a2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Title.java @@ -0,0 +1,61 @@ +/* + * 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.hql; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="title") +public class Title implements Serializable { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id_title") + private Integer id; + + private String description; + + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + + +}