/* * 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; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import javax.persistence.EntityManager; import javax.persistence.Query; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; import org.hibernate.dialect.MySQLDialect; import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest; import org.hibernate.jpa.test.metamodel.Customer; import org.hibernate.jpa.test.metamodel.Customer_; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; import org.junit.Test; /** * @author Steve Ebersole */ public class ManipulationCriteriaTest extends AbstractMetamodelSpecificTest { @Test public void basicTest() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); CriteriaBuilder builder = em.getCriteriaBuilder(); { CriteriaDelete<Customer> deleteCriteria = builder.createCriteriaDelete( Customer.class ); deleteCriteria.from( Customer.class ); em.createQuery( deleteCriteria ).executeUpdate(); } { CriteriaDelete<Customer> deleteCriteria = builder.createCriteriaDelete( Customer.class ); Root<Customer> root = deleteCriteria.from( Customer.class ); deleteCriteria.where( builder.equal( root.get( Customer_.name ), "Acme" ) ); em.createQuery( deleteCriteria ).executeUpdate(); } { CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); updateCriteria.from( Customer.class ); updateCriteria.set( Customer_.name, "Acme" ); em.createQuery( updateCriteria ).executeUpdate(); } { CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); Root<Customer> root = updateCriteria.from( Customer.class ); updateCriteria.set( Customer_.name, "Acme" ); updateCriteria.where( builder.equal( root.get( Customer_.name ), "Acme" ) ); em.createQuery( updateCriteria ).executeUpdate(); } em.getTransaction().commit(); em.close(); } @Test public void testNoAssignments() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); CriteriaBuilder builder = em.getCriteriaBuilder(); try { CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); updateCriteria.from( Customer.class ); em.createQuery( updateCriteria ).executeUpdate(); fail( "Expecting failure due to no assignments" ); } catch (IllegalArgumentException iae) { // expected } // changed to rollback since HHH-8442 causes transaction to be marked for rollback only assertTrue( em.getTransaction().getRollbackOnly() ); em.getTransaction().rollback(); em.close(); } @Test @TestForIssue(jiraKey = "HHH-8434") public void basicMultipleAssignments() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); updateCriteria.from( Customer.class ); updateCriteria.set( Customer_.name, "Bob" ); updateCriteria.set( Customer_.age, 99 ); em.createQuery( updateCriteria ).executeUpdate(); em.getTransaction().commit(); em.close(); } @Test public void testJoinsAndFetchesDisallowed() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); CriteriaBuilder builder = em.getCriteriaBuilder(); { try { CriteriaDelete<Customer> deleteCriteria = builder.createCriteriaDelete( Customer.class ); Root<Customer> root = deleteCriteria.from( Customer.class ); root.join( Customer_.spouse ); em.createQuery( deleteCriteria ).executeUpdate(); fail( "Expected failure dues to attempt to join" ); } catch (IllegalArgumentException expected) { } } { try { CriteriaDelete<Customer> deleteCriteria = builder.createCriteriaDelete( Customer.class ); Root<Customer> root = deleteCriteria.from( Customer.class ); root.fetch( Customer_.spouse ); em.createQuery( deleteCriteria ).executeUpdate(); fail( "Expected failure dues to attempt to fetch" ); } catch (IllegalArgumentException expected) { } } { try { CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); Root<Customer> root = updateCriteria.from( Customer.class ); root.join( Customer_.spouse ); em.createQuery( updateCriteria ).executeUpdate(); fail( "Expected failure dues to attempt to join" ); } catch (IllegalArgumentException expected) { } } { try { CriteriaUpdate<Customer> updateCriteria = builder.createCriteriaUpdate( Customer.class ); Root<Customer> root = updateCriteria.from( Customer.class ); root.fetch( Customer_.spouse ); em.createQuery( updateCriteria ).executeUpdate(); fail( "Expected failure dues to attempt to fetch" ); } catch (IllegalArgumentException expected) { } } em.getTransaction().commit(); em.close(); } @Test // MySQL does not allow "delete/update from" and subqueries to use the same table @SkipForDialect(MySQLDialect.class) public void testDeleteWithUnCorrelatedSubquery() { CriteriaBuilder builder = entityManagerFactory().getCriteriaBuilder(); EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); // attempt to delete Customers who's age is less than the AVG age CriteriaDelete<Customer> criteria = builder.createCriteriaDelete( Customer.class ); Root<Customer> customerRoot = criteria.from( Customer.class ); Subquery<Double> subCriteria = criteria.subquery( Double.class ); Root<Customer> subQueryCustomerRoot = subCriteria.from( Customer.class ); subCriteria.select( builder.avg( subQueryCustomerRoot.get( Customer_.age ) ) ); // also illustrates the new capability to use the subquery selection as an expression! criteria.where( builder.lessThan( customerRoot.get( Customer_.age ), subCriteria.getSelection().as( Integer.class ) ) ); // make sure Subquery#getParent fails... try { subCriteria.getParent(); fail( "Expecting Subquery.getParent call to fail on DELETE containing criteria" ); } catch (IllegalStateException expected) { } Query query = em.createQuery( criteria ); try { // first, make sure an attempt to list fails query.getResultList(); fail( "Attempt to getResultList() on delete criteria should have failed" ); } catch (IllegalStateException expected) { } query.executeUpdate(); em.getTransaction().commit(); em.close(); } }