/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.filter;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.junit.After;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.hamcrest.core.Is.is;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertThat;
/**
* @author Andrea Boriero
*/
@TestForIssue(jiraKey = "HHH-10991")
public class CriteriaQueryWithAppliedFilterTest extends BaseCoreFunctionalTestCase {
private final static Identifier STUDENT_ID = new Identifier( 2, new Identifier2( 4, 5L ) );
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {Student.class};
}
@Override
protected void prepareTest() throws Exception {
doInHibernate( this::sessionFactory, session -> {
final Student student = new Student();
student.setId( STUDENT_ID );
student.setName( "dre" );
student.setStatus( "active" );
student.setAge( 21 );
student.setAddress( new Address( "London", "Lollard St" ) );
session.save( student );
final Student student2 = new Student();
student2.setId( new Identifier( 4, new Identifier2( 4, 6L ) ) );
student2.setName( "Livia" );
student2.setStatus( "active" );
student2.setAge( 27 );
student2.setAddress( new Address( "London", "Oxford St" ) );
session.save( student2 );
});
}
@After
public void tearDown() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete from Student" ).executeUpdate();
} );
}
@Test
public void testSubquery() {
doInHibernate( this::sessionFactory, session -> {
final Criteria query = session.createCriteria( Student.class );
query.add( Restrictions.eq( "name", "dre" ) );
final DetachedCriteria inner = DetachedCriteria.forClass( Student.class );
inner.setProjection( Projections.min( "age" ) );
query.add( Property.forName( "age" ).eq( inner ) );
query.add( Restrictions.eq( "name", "dre" ) );
final List list = query.list();
assertThat( list.size(), is( 1 ) );
});
doInHibernate( this::sessionFactory, session -> {
session.enableFilter( "statusFilter" ).setParameter( "status", "deleted" );
final Criteria query = session.createCriteria( Student.class );
query.add( Restrictions.eq( "name", "dre" ) );
final DetachedCriteria inner = DetachedCriteria.forClass( Student.class );
inner.setProjection( Projections.min( "age" ) );
query.add( Property.forName( "age" ).eq( inner ) );
query.add( Restrictions.eq( "name", "dre" ) );
final List list = query.list();
assertThat( list.size(), is( 0 ) );
});
}
@Test
public void testSubqueryWithRestrictionsOnComponentTypes() {
doInHibernate( this::sessionFactory, session -> {
session.enableFilter( "statusFilter" ).setParameter( "status", "active" );
final Criteria query = session.createCriteria( Student.class );
query.add( Restrictions.eq( "id", STUDENT_ID ) );
final DetachedCriteria subSelect = DetachedCriteria.forClass( Student.class );
subSelect.setProjection( Projections.max( "age" ) );
subSelect.add( Restrictions.eq( "id", STUDENT_ID ) );
query.add( Property.forName( "age" ).eq( subSelect ) );
final List list = query.list();
assertThat( list.size(), is( 1 ) );
});
}
@Test
public void testSubqueryWithRestrictionsOnComponentTypes2() {
doInHibernate( this::sessionFactory, session -> {
session.enableFilter( "statusFilter" ).setParameter( "status", "active" );
final Criteria query = session.createCriteria( Student.class );
query.add( Restrictions.eq( "id", STUDENT_ID ) );
final DetachedCriteria subSelect = DetachedCriteria.forClass( Student.class );
subSelect.setProjection( Projections.max( "age" ) );
subSelect.add( Restrictions.eq( "address", new Address( "London", "Lollard St" ) ) );
subSelect.add( Restrictions.eq( "id", STUDENT_ID ) );
query.add( Property.forName( "age" ).eq( subSelect ) );
final List list = query.list();
assertThat( list.size(), is( 1 ) );
});
}
@Test
public void testRestrictionsOnComponentTypes() {
doInHibernate( this::sessionFactory, session -> {
session.enableFilter( "statusFilter" ).setParameter( "status", "active" );
final Criteria query = session.createCriteria( Student.class );
query.add( Restrictions.eq( "id", STUDENT_ID ) );
query.add( Restrictions.eq( "address", new Address( "London", "Lollard St" ) ) );
query.add( Restrictions.eq( "name", "dre" ) );
final List list = query.list();
assertThat( list.size(), is( 1 ) );
});
}
@FilterDef(
name = "statusFilter",
parameters = {
@ParamDef(
name = "status", type = "string"
)
}
)
@Filter(name = "statusFilter", condition = "STATUS = :status ")
@Entity(name = "Student")
@Table(name = "STUDENT")
public static class Student {
@EmbeddedId
private Identifier id;
private String name;
private int age;
@Column(name = "STATUS")
private String status;
@Embedded
private Address address;
public void setId(Identifier id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setStatus(String status) {
this.status = status;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(Address address) {
this.address = address;
}
}
@Embeddable
public static class Identifier implements Serializable {
private Integer id1;
@Embedded
private Identifier2 id2;
public Identifier() {
}
public Identifier(Integer id1, Identifier2 id2) {
this.id1 = id1;
this.id2 = id2;
}
}
@Embeddable
public static class Identifier2 implements Serializable {
private Integer id3;
private Long id4;
public Identifier2() {
}
public Identifier2(Integer id1, Long id2) {
this.id3 = id1;
this.id4 = id2;
}
}
@Embeddable
public static class Address implements Serializable {
private String city;
private String street;
public Address() {
}
public Address(String city, String street) {
this.city = city;
this.street = street;
}
}
}