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 845b739dacfd..35bf4e5346c9 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 @@ protected NotExpression(Criterion 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 f7c417549ac0..4faac80150a9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -2311,4 +2311,8 @@ public boolean useFollowOnLocking() { public UniqueDelegate getUniqueDelegate() { return uniqueDelegate; } + + 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 ac33edf5b058..62f8b2479ffc 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -396,4 +396,9 @@ public JDBCException convert(SQLException sqlException, String message, String s } }; } + + @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 faa634c6377b..123e38e24977 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 boolean forceLobAsLastValue() { 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 d0f0d8ce7943..22c11f6e0196 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 boolean supportsExistsInSelect() { 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 03ba24a86fc9..d20158d13027 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 void testCriteriaFetchMode() { 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(); + } }