/*
* 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.jpa.test.criteria.basic;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.jpa.test.metamodel.CreditCard;
import org.hibernate.jpa.test.metamodel.CreditCard_;
import org.hibernate.jpa.test.metamodel.Customer_;
import org.hibernate.jpa.test.metamodel.Order;
import org.hibernate.jpa.test.metamodel.Order_;
import org.hibernate.testing.TestForIssue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test the various predicates.
*
* @author Steve Ebersole
* @author Hardy Ferentschik
*/
public class PredicateTest extends AbstractMetamodelSpecificTest {
private CriteriaBuilder builder;
@Before
public void prepareTestData() {
builder = entityManagerFactory().getCriteriaBuilder();
EntityManager em = entityManagerFactory().createEntityManager();
em.getTransaction().begin();
em.persist( new Order( "order-1", 1.0d ) );
em.persist( new Order( "order-2", 10.0d ) );
em.persist( new Order( "order-3", new char[]{'r','u'} ) );
em.getTransaction().commit();
em.close();
}
@Test
public void testEmptyConjunction() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
// yes this is a retarded case, but explicitly allowed in the JPA spec
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
orderCriteria.where( builder.isTrue( builder.conjunction() ) );
em.createQuery( orderCriteria ).getResultList();
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.size() == 3 );
em.getTransaction().commit();
em.close();
}
@Test
public void testEmptyDisjunction() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
// yes this is a retarded case, but explicitly allowed in the JPA spec
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
orderCriteria.where( builder.isFalse( builder.disjunction() ) );
em.createQuery( orderCriteria ).getResultList();
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.size() == 3 );
em.getTransaction().commit();
em.close();
}
/**
* Check simple not.
*/
@Test
public void testSimpleNot() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
final Predicate p = builder.not( builder.equal( orderRoot.get( "id" ), "order-1" ) );
assertEquals( Predicate.BooleanOperator.AND, p.getOperator() );
orderCriteria.where( p );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertEquals( 2, orders.size() );
em.getTransaction().commit();
em.close();
}
/**
* Check simple not.
*/
@Test
public void testSimpleNot2() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
final Predicate p = builder.equal( orderRoot.get( "id" ), "order-1" ).not();
assertEquals( Predicate.BooleanOperator.AND, p.getOperator() );
orderCriteria.where( p );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertEquals( 2, orders.size() );
em.getTransaction().commit();
em.close();
}
/**
* Check complicated not.
*/
@Test
public void testComplicatedNotOr() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p1 = builder.equal( orderRoot.get( "id" ), "order-1" );
Predicate p2 = builder.equal( orderRoot.get( "id" ), "order-2" );
Predicate compoundPredicate = builder.not( builder.or( p1, p2 ) );
// negated OR should become an AND
assertEquals( Predicate.BooleanOperator.AND, compoundPredicate.getOperator() );
orderCriteria.where( compoundPredicate );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertEquals( 1, orders.size() );
Order order = orders.get( 0 );
assertEquals( "order-3", order.getId() );
em.getTransaction().commit();
em.close();
}
/**
* Check complicated not.
*/
@Test
public void testNotMultipleOr() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p1 = builder.equal( orderRoot.get( "id" ), "order-1" );
Predicate p2 = builder.equal( orderRoot.get( "id" ), "order-2" );
Predicate p3 = builder.equal( orderRoot.get( "id" ), "order-3" );
final Predicate compoundPredicate = builder.or( p1, p2, p3 ).not();
// negated OR should become an AND
assertEquals( Predicate.BooleanOperator.AND, compoundPredicate.getOperator() );
orderCriteria.where( compoundPredicate );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertEquals( 0, orders.size() );
em.getTransaction().commit();
em.close();
}
/**
* Check complicated not.
*/
@Test
public void testComplicatedNotAnd() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p1 = builder.equal( orderRoot.get( "id" ), "order-1" );
Predicate p2 = builder.equal( orderRoot.get( "id" ), "order-2" );
Predicate compoundPredicate = builder.and( p1, p2 ).not();
// a negated AND should become an OR
assertEquals( Predicate.BooleanOperator.OR, compoundPredicate.getOperator() );
orderCriteria.where( compoundPredicate );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertEquals( 3, orders.size() );
em.getTransaction().commit();
em.close();
}
/**
* Check predicate for field which has simple char array type (char[]).
*/
@Test
public void testCharArray() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p = builder.equal( orderRoot.get( "domen" ), new char[]{'r','u'} );
orderCriteria.where( p );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.size() == 1 );
em.getTransaction().commit();
em.close();
}
/**
* Check predicate for field which has simple char array type (byte[]).
*/
@Test
public void testByteArray() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p = builder.equal( orderRoot.get( "number" ), new byte[]{'1','2'} );
orderCriteria.where( p );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.size() == 0 );
em.getTransaction().commit();
em.close();
}
@Test
@TestForIssue( jiraKey = "HHH-5803" )
public void testQuotientConversion() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
Long longValue = 999999999L;
Path<Double> doublePath = orderRoot.get( Order_.totalPrice );
Path<Integer> integerPath = orderRoot.get( Order_.customer ).get( Customer_.age );
orderCriteria.select( orderRoot );
Predicate p = builder.ge(
builder.quot( integerPath, doublePath ),
longValue
);
orderCriteria.where( p );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.size() == 0 );
em.getTransaction().commit();
em.close();
}
@Test
public void testExplicitBuilderBooleanHandling() {
// just checking syntax of the resulting query
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
// note : these may fail on various matrix db jobs depending on how the dialect handles booleans
{
CriteriaQuery<CreditCard> criteriaQuery = builder.createQuery( CreditCard.class );
Root<CreditCard> root = criteriaQuery.from( CreditCard.class );
criteriaQuery.where( builder.isFalse( root.get( CreditCard_.approved ) ) );
em.createQuery( criteriaQuery ).getResultList();
}
{
CriteriaQuery<Order> criteriaQuery = builder.createQuery( Order.class );
Root<Order> root = criteriaQuery.from( Order.class );
criteriaQuery.where( builder.isFalse( root.get( Order_.creditCard ).get( CreditCard_.approved ) ) );
em.createQuery( criteriaQuery ).getResultList();
}
em.getTransaction().commit();
em.close();
}
}