HHH-10874 - @Where annotation is not processed with "Extra-lazy" loading for bidirectional collections

For bidirectional collections, the  where clause is now considered when calculating the size() of the LazyCollectionOption.EXTRA annotated collections
This commit is contained in:
mharray 2016-06-21 16:23:40 +12:00 committed by Vlad Mihalcea
parent eec01edcca
commit 253820a289
6 changed files with 298 additions and 6 deletions

View File

@ -1012,6 +1012,7 @@ public abstract class AbstractCollectionPersister
return new SimpleSelect( dialect )
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addWhereToken( sqlWhereString )
.addColumn( selectValue )
.toStatementString();
}
@ -1025,6 +1026,7 @@ public abstract class AbstractCollectionPersister
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getIndexColumnNames(), "=?" )
.addCondition( indexFormulas, "=?" )
.addWhereToken( sqlWhereString )
.addColumn( "1" )
.toStatementString();
}
@ -1038,6 +1040,7 @@ public abstract class AbstractCollectionPersister
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getIndexColumnNames(), "=?" )
.addCondition( indexFormulas, "=?" )
.addWhereToken( sqlWhereString )
.addColumns( getElementColumnNames(), elementColumnAliases )
.addColumns( indexFormulas, indexColumnAliases )
.toStatementString();
@ -1049,6 +1052,7 @@ public abstract class AbstractCollectionPersister
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getElementColumnNames(), "=?" )
.addCondition( elementFormulas, "=?" )
.addWhereToken( sqlWhereString )
.addColumn( "1" )
.toStatementString();
}

View File

@ -96,7 +96,12 @@ public class SimpleSelect {
}
public SimpleSelect addWhereToken(String token) {
whereTokens.add( token );
if (token != null ) {
if (!whereTokens.isEmpty()) {
and();
}
whereTokens.add( token );
}
return this;
}

View File

@ -0,0 +1,44 @@
package org.hibernate.test.extralazy;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.Where;
@Entity
@Table(name = "championship")
public class Championship {
@Id
private int id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.EXTRA)
@Where(clause = " gpa >= 4 ")
private List<Student> students = new ArrayList<>();
public Championship() {}
public Championship(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Student> getStudents() {
return students;
}
}

View File

@ -5,11 +5,6 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.extralazy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Map;
@ -19,11 +14,18 @@ import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* @author Gavin King
*/
@ -32,6 +34,11 @@ public class ExtraLazyTest extends BaseCoreFunctionalTestCase {
public String[] getMappings() {
return new String[] { "extralazy/UserGroup.hbm.xml","extralazy/Parent.hbm.xml","extralazy/Child.hbm.xml" };
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { School.class, Student.class, Championship.class };
}
@Test
public void testOrphanDelete() {
@ -248,5 +255,90 @@ public class ExtraLazyTest extends BaseCoreFunctionalTestCase {
assertNotNull(child2);
session2.close();
}
@Test
@TestForIssue(jiraKey = "HHH-10874")
public void testWhereClauseOnBidirectionalCollection() {
Session s = openSession();
Transaction t = s.beginTransaction();
School school = new School(1);
s.persist(school);
Student gavin = new Student("gavin", 4);
Student turin = new Student("turin", 3);
Student mike = new Student("mike", 5);
Student fred = new Student("fred", 2);
gavin.setSchool(school);
turin.setSchool(school);
mike.setSchool(school);
fred.setSchool(school);
s.persist(gavin);
s.persist(turin);
s.persist(mike);
s.persist(fred);
t.commit();
s.close();
s = openSession();
School school2 = s.get(School.class, 1);
assertEquals(4, school2.getStudents().size());
assertEquals( 2, school2.getTopStudents().size() );
assertTrue( school2.getTopStudents().contains( gavin ) );
assertTrue( school2.getTopStudents().contains( mike ) );
assertEquals(2, school2.getStudentsMap().size() );
assertTrue( school2.getStudentsMap().containsKey( gavin.getId() ) );
assertTrue( school2.getStudentsMap().containsKey( mike.getId() ) );
s.close();
}
@Test
@FailureExpected( jiraKey = "HHH-3319" )
public void testWhereClauseOnUnidirectionalCollection() {
Session s = openSession();
Transaction t = s.beginTransaction();
Championship championship = new Championship( 1 );
s.persist(championship);
Student gavin = new Student("gavin", 4);
Student turin = new Student("turin", 3);
Student mike = new Student("mike", 5);
Student fred = new Student("fred", 2);
championship.getStudents().add( gavin );
championship.getStudents().add( turin );
championship.getStudents().add( mike );
championship.getStudents().add( fred );
s.persist(gavin);
s.persist(turin);
s.persist(mike);
s.persist(fred);
t.commit();
s.close();
s = openSession();
Championship championship2 = s.get(Championship.class, 1);
assertEquals( 2, championship2.getStudents().size() );
assertTrue( championship2.getStudents().contains( gavin ) );
assertTrue( championship2.getStudents().contains( mike ) );
s.close();
}
@Override
protected boolean rebuildSessionFactoryOnError() {
return false;
}
}

View File

@ -0,0 +1,64 @@
package org.hibernate.test.extralazy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.Where;
@Entity
@Table(name = "school")
public class School {
@Id
private int id;
@OneToMany(mappedBy = "school")
@LazyCollection(LazyCollectionOption.EXTRA)
private Set<Student> students = new HashSet<Student>();
@OneToMany(mappedBy = "school")
@LazyCollection(LazyCollectionOption.EXTRA)
@Where(clause = " gpa >= 4 ")
private Set<Student> topStudents = new HashSet<Student>();
@OneToMany(mappedBy = "school")
@LazyCollection(LazyCollectionOption.EXTRA)
@Where(clause = " gpa >= 4 ")
@MapKey
private Map<String, Student> studentsMap = new HashMap<>();
public School() {}
public School(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Set<Student> getStudents() {
return students;
}
public Set<Student> getTopStudents() {
return topStudents;
}
public Map<String, Student> getStudentsMap() {
return studentsMap;
}
}

View File

@ -0,0 +1,83 @@
package org.hibernate.test.extralazy;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import static javax.persistence.GenerationType.IDENTITY;
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = IDENTITY)
private String id;
@ManyToOne
private School school;
private String firstName;
private int gpa;
public Student() {}
public Student(String firstName, int gpa) {
this.firstName = firstName;
this.gpa = gpa;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int getGpa() {
return gpa;
}
public void setGpa(int gpa) {
this.gpa = gpa;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( !( o instanceof Student ) ) {
return false;
}
Student student = (Student) o;
return Objects.equals( getFirstName(), student.getFirstName() );
}
@Override
public int hashCode() {
return Objects.hash( getFirstName() );
}
}