HHH-4959 : change default for hibernate.query.conventional_java_constants to false

This commit is contained in:
Gail Badner 2018-01-09 20:53:43 -08:00
parent d0059cdef9
commit 9e6585b804
6 changed files with 311 additions and 10 deletions

View File

@ -290,13 +290,15 @@ Should we strictly adhere to JPA Query Language (JPQL) syntax, or more broadly s
Setting this to `true` may cause valid HQL to throw an exception because it violates the JPQL subset.
|`hibernate.query.startup_check` | `true` (default value) or `false` |Should named queries be checked during startup?
|`hibernate.query.conventional_java_constants` | `true` (default value) or `false` |
|`hibernate.query.conventional_java_constants` | `true` or `false` (default value) |
Setting which indicates whether or not Java constant follow the https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html[Java Naming conventions].
Default is `true`.
Existing applications may want to disable this (set it `false`) if non-conventional Java constants are used.
However, there is a significant performance overhead for using non-conventional Java constants
since Hibernate cannot determine if aliases should be treated as Java constants or not.
Default is `false`.
Existing applications may want to enable this (set it to `true`) if only conventional Java constants are used.
There is a significant performance improvement by setting `hibernate.query.conventional_java_constants` to `true`, because Hibernate can determine if an alias should be treated as a Java constant by simply checking if the alias follows Java constant conventions.
With `hibernate.query.conventional_java_constants` set to `false`, Hibernate determines if an alias should be treated as a Java constant by attempting to load the alias as a class (an expensive operation); if it fails, then Hibernate treats the alias as a Java constant.
Check out https://hibernate.atlassian.net/browse/HHH-4959[HHH-4959] for more details.

View File

@ -602,7 +602,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
this.strictJpaQueryLanguageCompliance = cfgService.getSetting( JPAQL_STRICT_COMPLIANCE, BOOLEAN, false );
this.namedQueryStartupCheckingEnabled = cfgService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true );
this.conventionalJavaConstants = cfgService.getSetting(
CONVENTIONAL_JAVA_CONSTANTS, BOOLEAN, true );
CONVENTIONAL_JAVA_CONSTANTS, BOOLEAN, false );
this.procedureParameterNullPassingEnabled = cfgService.getSetting( PROCEDURE_NULL_PARAM_PASSING, BOOLEAN, false );
this.collectionJoinSubqueryRewriteEnabled = cfgService.getSetting( COLLECTION_JOIN_SUBQUERY, BOOLEAN, true );

View File

@ -565,11 +565,18 @@ public interface AvailableSettings {
/**
* Setting which indicates whether or not Java constant follow the Java Naming conventions.
* <p/>
* Default is {@code true}. Existing applications may want to disable this (set it {@code false}) if non-conventional Java constants are used.
* However, there is a significant performance overhead for using non-conventional Java constants since Hibernate cannot determine if aliases
* should be treated as Java constants or not.
* Default is {@code false}. Existing applications may want to enable this (set it to {@code true})
* if only conventional Java constants are used.
* <p/>
* There is a significant performance improvement by setting {@code hibernate.query.conventional_java_constants}
* to {@code true}, because Hibernate can determine if an alias should be treated as a Java constant by simply
* checking if the alias follows Java constant conventions.
* <p/>
* With {@code hibernate.query.conventional_java_constants} set to {@code false}, Hibernate determines if an alias
* should be treated as a Java constant by attempting to load the alias as a class (an expensive operation);
* if it fails, then Hibernate treats the alias as a Java constant.
*
* @since 5.2
* @since 5.1.11, 5.2
*/
String CONVENTIONAL_JAVA_CONSTANTS = "hibernate.query.conventional_java_constants";

View File

@ -0,0 +1,98 @@
/*
* 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.test.queryconstant;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
/**
* @author Gail Badner
*/
public class NonConventionalJavaConstantAllowedTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { AnEntity.class };
}
@Override
@SuppressWarnings("unchecked")
protected void addSettings(Map settings) {
super.addSettings( settings );
settings.put( AvailableSettings.CONVENTIONAL_JAVA_CONSTANTS, "false" );
}
@Before
public void setup() {
Session s = openSession();
s.getTransaction().begin();
AnEntity anEntity = new AnEntity();
anEntity.operationType = OPERATION_TYPE.CREATE;
s.persist( anEntity );
s.getTransaction().commit();
s.clear();
}
@After
public void cleanup() {
Session s = openSession();
s.getTransaction().begin();
s.createQuery( "delete from AnEntity" ).executeUpdate();
s.getTransaction().commit();
s.clear();
}
@Test
@TestForIssue( jiraKey = "HHH-4959")
public void testDisabled() {
assertFalse( sessionFactory().getSessionFactoryOptions().isConventionalJavaConstants() );
Session s = openSession();
s.getTransaction().begin();
AnEntity anEntity = (AnEntity) s.createQuery(
"from AnEntity e where e.operationType = org.hibernate.test.queryconstant.NonConventionalJavaConstantDefaultTest$OPERATION_TYPE.CREATE"
).uniqueResult();
assertNotNull( anEntity );
s.getTransaction().commit();
s.close();
}
public enum OPERATION_TYPE {
CREATE, UPDATE, DELETE
}
@Entity(name = "AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private long id;
OPERATION_TYPE operationType;
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.test.queryconstant;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
/**
* @author Gail Badner
*/
public class NonConventionalJavaConstantDefaultTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { AnEntity.class };
}
@Before
public void setup() {
Session s = openSession();
s.getTransaction().begin();
AnEntity anEntity = new AnEntity();
anEntity.operationType = OPERATION_TYPE.CREATE;
s.persist( anEntity );
s.getTransaction().commit();
s.clear();
}
@After
public void cleanup() {
Session s = openSession();
s.getTransaction().begin();
s.createQuery( "delete from AnEntity" ).executeUpdate();
s.getTransaction().commit();
s.clear();
}
@Test
@TestForIssue( jiraKey = "HHH-4959")
public void testDefault() {
// check default
assertFalse( sessionFactory().getSessionFactoryOptions().isConventionalJavaConstants() );
Session s = openSession();
s.getTransaction().begin();
AnEntity anEntity = (AnEntity) s.createQuery(
"from AnEntity e where e.operationType = org.hibernate.test.queryconstant.NonConventionalJavaConstantDefaultTest$OPERATION_TYPE.CREATE"
).uniqueResult();
assertNotNull( anEntity );
s.getTransaction().commit();
s.close();
}
public enum OPERATION_TYPE {
CREATE, UPDATE, DELETE
}
@Entity(name = "AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private long id;
OPERATION_TYPE operationType;
}
}

View File

@ -0,0 +1,105 @@
/*
* 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.test.queryconstant;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.hql.internal.ast.QuerySyntaxException;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Gail Badner
*/
public class NonConventionalJavaConstantDisallowedTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { AnEntity.class };
}
@Override
@SuppressWarnings("unchecked")
protected void addSettings(Map settings) {
super.addSettings( settings );
settings.put( AvailableSettings.CONVENTIONAL_JAVA_CONSTANTS, "true" );
}
@Before
public void setup() {
Session s = openSession();
s.getTransaction().begin();
AnEntity anEntity = new AnEntity();
anEntity.operationType = OPERATION_TYPE.CREATE;
s.persist( anEntity );
s.getTransaction().commit();
s.clear();
}
@After
public void cleanup() {
Session s = openSession();
s.getTransaction().begin();
s.createQuery( "delete from AnEntity" ).executeUpdate();
s.getTransaction().commit();
s.clear();
}
@Test
@TestForIssue( jiraKey = "HHH-4959")
public void testEnabled() {
assertTrue( sessionFactory().getSessionFactoryOptions().isConventionalJavaConstants() );
Session s = openSession();
s.getTransaction().begin();
try {
AnEntity anEntity = (AnEntity) s.createQuery(
"from AnEntity e where e.operationType = org.hibernate.test.queryconstant.NonConventionalJavaConstantDefaultTest$OPERATION_TYPE.CREATE"
).uniqueResult();
fail( "should have thrown QuerySyntaxException" );
}
catch (QuerySyntaxException expected) {
// expected
}
finally {
s.getTransaction().rollback();
s.close();
}
}
public enum OPERATION_TYPE {
CREATE, UPDATE, DELETE
}
@Entity(name = "AnEntity")
public static class AnEntity {
@Id
@GeneratedValue
private long id;
OPERATION_TYPE operationType;
}
}