From e3419f6d722a276fd846178ee59b3176a9fb0da7 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Mon, 30 Sep 2013 16:34:26 -0400 Subject: [PATCH] HHH-8578 correct DeleteExecutor's use of where-clause --- .../hql/internal/ast/exec/DeleteExecutor.java | 21 ++++-- .../test/hql/BulkManipulationTest.java | 56 +++++++++++---- .../java/org/hibernate/test/hql/Crop.java | 69 +++++++++++++++++++ .../java/org/hibernate/test/hql/Farm.java | 68 ++++++++++++++++++ 4 files changed, 194 insertions(+), 20 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/Crop.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/hql/Farm.java diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java index daf8d18d5e..e7752470ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java @@ -64,13 +64,21 @@ public class DeleteExecutor extends BasicExecutor { final SessionFactoryImplementor factory = walker.getSessionFactoryHelper().getFactory(); final Dialect dialect = factory.getDialect(); - final DeleteStatement deleteStatement = ( DeleteStatement ) walker.getAST(); - final AST whereClause = deleteStatement.getWhereClause(); - try { - final SqlGenerator gen = new SqlGenerator( factory ); - gen.whereClause( whereClause ); - parameterSpecifications = gen.getCollectedParameters(); + final DeleteStatement deleteStatement = ( DeleteStatement ) walker.getAST(); + + final String idSubselectWhere; + if (deleteStatement.hasWhereClause()) { + final AST whereClause = deleteStatement.getWhereClause(); + final SqlGenerator gen = new SqlGenerator( factory ); + gen.whereClause( whereClause ); + parameterSpecifications = gen.getCollectedParameters(); + idSubselectWhere = gen.getSQL().length() > 7 ? gen.getSQL() : ""; + } + else { + parameterSpecifications = new ArrayList(); + idSubselectWhere = ""; + } // If many-to-many, delete the FK row in the collection table. for ( Type type : persister.getPropertyTypes() ) { @@ -86,7 +94,6 @@ public class DeleteExecutor extends BasicExecutor { " the constraints or manually clear the associations prior to deleting the entities." ); } else { - final String idSubselectWhere = gen.getSQL().length() > 7 ? gen.getSQL() : ""; final String idSubselect = "(select " + StringHelper.join( ", ", persister.getIdentifierColumnNames() ) + " from " + persister.getTableName() + idSubselectWhere + ")"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java index 779c5cdfa3..22f9031b7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java @@ -30,9 +30,7 @@ import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.List; -import java.util.Map; import junit.framework.AssertionFailedError; @@ -73,6 +71,10 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { }; } + protected Class[] getAnnotatedClasses() { + return new Class[] { Farm.class, Crop.class }; + } + @Test public void testDeleteNonExistentEntity() { Session s = openSession(); @@ -1193,11 +1195,48 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { } @Test - @TestForIssue( jiraKey = "HHH-1917" ) + @TestForIssue( jiraKey = "HHH-8476" ) public void testManyToManyBulkDelete() { Session s = openSession(); Transaction t = s.beginTransaction(); + Farm farm1 = new Farm(); + farm1.setName( "farm1" ); + Crop crop = new Crop(); + crop.setName( "crop1" ); + farm1.setCrops( new ArrayList() ); + farm1.getCrops().add( crop ); + s.save( farm1 ); + + Farm farm2 = new Farm(); + farm2.setName( "farm2" ); + farm2.setCrops( new ArrayList() ); + farm2.getCrops().add( crop ); + s.save( farm2 ); + + s.flush(); + + try { + s.createQuery( "delete from Farm f where f.name='farm1'" ).executeUpdate(); + assertEquals( s.createQuery( "from Farm" ).list().size(), 1 ); + s.createQuery( "delete from Farm" ).executeUpdate(); + assertEquals( s.createQuery( "from Farm" ).list().size(), 0 ); + } + catch (ConstraintViolationException cve) { + fail("The join table was not cleared prior to the bulk delete."); + } + finally { + t.rollback(); + s.close(); + } + } + + @Test + @TestForIssue( jiraKey = "HHH-1917" ) + public void testManyToManyBulkDeleteMultiTable() { + Session s = openSession(); + Transaction t = s.beginTransaction(); + Human friend = new Human(); friend.setName( new Name( "Bob", 'B', "Bobbert" ) ); s.save( friend ); @@ -1210,19 +1249,10 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { s.flush(); - Zoo zoo = new Zoo(); - Map directors = new HashMap(); - directors.put( brett.getId().toString(), brett ); - zoo.setDirectors( directors ); - s.save( zoo ); - - s.flush(); - try { - // non-multitable - s.createQuery( "delete from Zoo" ).executeUpdate(); // multitable (joined subclass) s.createQuery( "delete from Human" ).executeUpdate(); + assertEquals( s.createQuery( "from Human" ).list().size(), 0 ); } catch (ConstraintViolationException cve) { fail("The join table was not cleared prior to the bulk delete."); diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Crop.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Crop.java new file mode 100644 index 0000000000..5e927f186b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Crop.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * 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, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.hql; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +/** + * @author Brett Meyer + */ +@Entity +public class Crop { + + @Id @GeneratedValue + private long id; + + private String name; + + @ManyToMany(mappedBy = "crops", cascade = CascadeType.ALL) + private List farms; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getFarms() { + return farms; + } + + public void setFarms(List farms) { + this.farms = farms; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/Farm.java b/hibernate-core/src/test/java/org/hibernate/test/hql/Farm.java new file mode 100644 index 0000000000..a3abd13373 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/Farm.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * 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, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.hql; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +/** + * @author Brett Meyer + */ +@Entity +public class Farm { + + @Id @GeneratedValue + private long id; + + private String name; + + @ManyToMany(cascade = CascadeType.ALL) + private List crops; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getCrops() { + return crops; + } + + public void setCrops(List crops) { + this.crops = crops; + } +}