From bfcca649976dab410f3cada09bfd0bfd88befbf8 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Thu, 3 Jan 2013 15:59:26 -0500 Subject: [PATCH] HHH-6643 Criteria doesn't support a chaining of 2 not restrictions (sql = not not criterion) --- .../hibernate/criterion/NotExpression.java | 13 +++---- .../java/org/hibernate/dialect/Dialect.java | 4 +++ .../org/hibernate/dialect/MySQLDialect.java | 5 +++ .../hibernate/dialect/Oracle8iDialect.java | 5 +++ .../org/hibernate/dialect/Oracle9Dialect.java | 5 +++ .../test/criteria/CriteriaQueryTest.java | 35 +++++++++++++++++++ 6 files changed, 58 insertions(+), 9 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/criterion/NotExpression.java b/hibernate-core/src/main/java/org/hibernate/criterion/NotExpression.java index 845b739dac..35bf4e5346 100644 --- a/hibernate-core/src/main/java/org/hibernate/criterion/NotExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/criterion/NotExpression.java @@ -25,12 +25,12 @@ package org.hibernate.criterion; import org.hibernate.Criteria; import org.hibernate.HibernateException; -import org.hibernate.dialect.MySQLDialect; import org.hibernate.engine.spi.TypedValue; /** * Negates another criterion * @author Gavin King + * @author Brett Meyer */ public class NotExpression implements Criterion { @@ -40,14 +40,9 @@ public class NotExpression implements Criterion { this.criterion = criterion; } - public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) - throws HibernateException { - if ( criteriaQuery.getFactory().getDialect() instanceof MySQLDialect ) { - return "not (" + criterion.toSqlString(criteria, criteriaQuery) + ')'; - } - else { - return "not " + criterion.toSqlString(criteria, criteriaQuery); - } + public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { + return criteriaQuery.getFactory().getDialect().getNotExpression( + criterion.toSqlString( criteria, criteriaQuery ) ); } public TypedValue[] getTypedValues( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 1303785e34..dcaf3e5038 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -2381,4 +2381,8 @@ public abstract class Dialect implements ConversionContext { public boolean supportsNotNullUnique() { return true; } + + public String getNotExpression( String expression ) { + return "not " + expression; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index e9825d0ca8..5d9d881577 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -415,4 +415,9 @@ public class MySQLDialect extends Dialect { } }; } + + @Override + public String getNotExpression( String expression ) { + return "not (" + expression + ")"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index faa634c637..123e38e249 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -581,4 +581,9 @@ public class Oracle8iDialect extends Dialect { public boolean useFollowOnLocking() { return true; } + + @Override + public String getNotExpression( String expression ) { + return "not (" + expression + ")"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java index d0f0d8ce79..22c11f6e01 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java @@ -377,4 +377,9 @@ public class Oracle9Dialect extends Dialect { public int getInExpressionCountLimit() { return PARAM_LIST_SIZE_LIMIT; } + + @Override + public String getNotExpression( String expression ) { + return "not (" + expression + ")"; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java b/hibernate-core/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java index 03ba24a86f..d20158d130 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/criteria/CriteriaQueryTest.java @@ -2011,6 +2011,41 @@ public class CriteriaQueryTest extends BaseCoreFunctionalTestCase { session.close(); } + + @Test + @TestForIssue( jiraKey = "HHH-6643" ) + public void testNotNot() { + Student student1 = new Student(); + student1.setName("Foo1 Foo1"); + student1.setStudentNumber(1); + Student student2 = new Student(); + student2.setName("Foo2 Foo2"); + student2.setStudentNumber(2); + + Session s = openSession(); + Transaction t = s.beginTransaction(); + + s.persist( student1 ); + s.persist( student2 ); + s.flush(); + s.clear(); + + // Although this example is simplified and the "not not" is pointless, + // double negatives can occur in some dynamic applications (regardless + // if it results from bad design or not). Test to ensure the dialect + // handles them as expected. + List students = s.createCriteria( Student.class ).add( + Restrictions.not( + Restrictions.not( + Restrictions.eq( "studentNumber", 1l ) ) ) + ).list(); + + assertEquals( students.size(), 1 ); + assertEquals( students.get( 0 ).getStudentNumber(), 1 ); + + t.commit(); + session.close(); + } }