Re-enabled additional tests

This commit is contained in:
Andrea Boriero 2021-11-25 17:15:22 +01:00 committed by Andrea Boriero
parent e7992a35d4
commit 0e1822e5dd
5 changed files with 421 additions and 387 deletions

View File

@ -93,7 +93,7 @@ public class OracleDialect extends Dialect {
private static final Pattern GROUP_BY_KEYWORD_PATTERN = Pattern.compile( "\\bgroup\\sby\\b" );
private static final Pattern ORDER_BY_KEYWORD_PATTERN = Pattern.compile( "\\border\\sby\\b" );
private static final Pattern UNION_KEYWORD_PATTERN = Pattern.compile( "\\bunion\\b" );
private static final Pattern SQL_STATEMENT_TYPE_PATTERN = Pattern.compile("^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*?");
private static final Pattern SQL_STATEMENT_TYPE_PATTERN = Pattern.compile("^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*?", Pattern.CASE_INSENSITIVE);
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";

View File

@ -0,0 +1,212 @@
/*
* 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.orm.test.queryhint;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Root;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Brett Meyer
*/
@RequiresDialect(value = OracleDialect.class, version = 800)
@DomainModel(
annotatedClasses = { OracleQueryHintTest.Employee.class, OracleQueryHintTest.Department.class }
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = @Setting(name = AvailableSettings.USE_SQL_COMMENTS, value = "true")
)
public class OracleQueryHintTest {
@BeforeAll
protected void setUp(SessionFactoryScope scope) {
Department department = new Department();
department.name = "Sales";
Employee employee1 = new Employee();
employee1.department = department;
Employee employee2 = new Employee();
employee2.department = department;
scope.inTransaction( s -> {
s.persist( department );
s.persist( employee1 );
s.persist( employee2 );
} );
}
@Test
public void testQueryHint(SessionFactoryScope scope) {
final SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
// test Query w/ a simple Oracle optimizer hint
scope.inTransaction( s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals( 2, results.size() );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
statementInspector.clear();
// test multiple hints
scope.inTransaction( s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.addQueryHint( "USE_CONCAT" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals( results.size(), 2 );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS, USE_CONCAT */" ) );
statementInspector.clear();
// ensure the insertion logic can handle a comment appended to the front
scope.inTransaction( s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.setComment( "this is a test" )
.addQueryHint( "ALL_ROWS" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals( results.size(), 2 );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
statementInspector.clear();
// test Criteria
scope.inTransaction( s -> {
final CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = criteriaBuilder.createQuery( Employee.class );
Root<Employee> root = criteria.from( Employee.class );
Join<Object, Object> departmentJoin = root.join( "department" );
criteria.select( root ).where( criteriaBuilder.equal( departmentJoin.get( "name" ), "Sales" ) );
// Criteria criteria = s.createCriteria( Employee.class )
// .addQueryHint( "ALL_ROWS" )
// .createCriteria( "department" ).add( Restrictions.eq( "name", "Sales" ) );
Query<Employee> query = s.createQuery( criteria );
query.addQueryHint( "ALL_ROWS" );
List results = query.list();
assertEquals( results.size(), 2 );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
statementInspector.clear();
}
@Test
@TestForIssue(jiraKey = "HHH-12362")
public void testQueryHintAndComment(SessionFactoryScope scope) {
final SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setComment( "My_Query" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals( results.size(), 2 );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries()
.get( 0 )
.contains( "/* My_Query */ select /*+ ALL_ROWS */" ) );
statementInspector.clear();
}
@Test
@TestForIssue(jiraKey = "HHH-13608")
public void testQueryHintCaseInsensitive(SessionFactoryScope scope) {
final SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( s -> {
List results = s.createNativeQuery(
"SELECT e.id as id " +
"FROM Employee e " +
"JOIN Department d ON e.department_id = d.id " +
"WHERE d.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setComment( "My_Query" )
.setParameter( "departmentName", "Sales" )
.getResultList();
assertEquals( results.size(), 2 );
} );
statementInspector.assertExecutedCount( 1 );
assertTrue( statementInspector.getSqlQueries()
.get( 0 )
.contains( "/* My_Query */ SELECT /*+ ALL_ROWS */" ) );
statementInspector.clear();
}
@Entity(name = "Employee")
public static class Employee {
@Id
@GeneratedValue
public long id;
@ManyToOne(fetch = FetchType.LAZY)
public Department department;
}
@Entity(name = "Department")
public static class Department {
@Id
@GeneratedValue
public long id;
public String name;
}
}

View File

@ -0,0 +1,208 @@
/*
* 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.orm.test.queryhint;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.query.Query;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SettingProvider;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Root;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Brett Meyer
*/
@RequiresDialect(value = SQLServerDialect.class, version = 11)
@DomainModel(
annotatedClasses = { QueryHintSQLServer2012Test.Employee.class, QueryHintSQLServer2012Test.Department.class }
)
@SessionFactory
@ServiceRegistry(
settings = @Setting(name = AvailableSettings.USE_SQL_COMMENTS, value = "true"),
settingProviders = @SettingProvider(provider = QueryHintSQLServer2012Test.DialectProvider.class, settingName = AvailableSettings.DIALECT)
)
public class QueryHintSQLServer2012Test {
public static class DialectProvider implements SettingProvider.Provider<String> {
@Override
public String getSetting() {
return QueryHintTestSQLServer2012Dialect.class.getName();
}
}
@Test
public void testQueryHint(SessionFactoryScope scope) {
Department department = new Department();
department.name = "Sales";
Employee employee1 = new Employee();
employee1.department = department;
Employee employee2 = new Employee();
employee2.department = department;
List result = scope.fromSession(
session -> {
session.getTransaction().begin();
session.persist( department );
session.persist( employee1 );
session.persist( employee2 );
try {
session.getTransaction().commit();
session.clear();
// test Query w/ a simple SQLServer2012 optimizer hint
session.getTransaction().begin();
Query query = session.createQuery(
"FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" )
.addQueryHint(
"MAXDOP 2" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
session.getTransaction().commit();
session.clear();
assertEquals( 2, results.size() );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql()
.contains( "OPTION (MAXDOP 2)" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// test multiple hints
session.getTransaction().begin();
query = session.createQuery(
"FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "MAXDOP 2" )
.addQueryHint( "CONCAT UNION" )
.setParameter( "departmentName", "Sales" );
results = query.list();
session.getTransaction().commit();
session.clear();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "MAXDOP 2" ) );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "CONCAT UNION" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// ensure the insertion logic can handle a comment appended to the front
session.getTransaction().begin();
query = session.createQuery(
"FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" )
.setComment( "this is a test" )
.addQueryHint( "MAXDOP 2" )
.setParameter( "departmentName", "Sales" );
results = query.list();
session.getTransaction().commit();
session.clear();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql()
.contains( "OPTION (MAXDOP 2)" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// test Criteria
session.getTransaction().begin();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = criteriaBuilder.createQuery( Employee.class );
Root<Employee> root = criteria.from( Employee.class );
Join<Object, Object> departement = root.join( "department", JoinType.INNER );
criteria.select( root ).where( criteriaBuilder.equal( departement.get( "name" ), "Sales" ) );
// Criteria criteria = s.createCriteria( Employee.class ).addQueryHint( "MAXDOP 2" ).createCriteria( "department" )
// .add( Restrictions.eq( "name", "Sales" ) );
// results = criteria.list();
Query<Employee> criteriaQuery = session.createQuery( criteria );
criteriaQuery.addQueryHint( "MAXDOP 2" );
results = criteriaQuery.list();
session.getTransaction().commit();
return results;
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
);
assertEquals( result.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "OPTION (MAXDOP 2)" ) );
}
/**
* Since the query hint is added to the SQL during Loader's executeQueryStatement -> preprocessSQL, rather than
* early on during the QueryTranslator or QueryLoader initialization, there's not an easy way to check the full SQL
* after completely processing it. Instead, use this ridiculous hack to ensure Loader actually calls Dialect. TODO:
* This is terrible. Better ideas?
*/
public static class QueryHintTestSQLServer2012Dialect extends SQLServer2012Dialect {
private static String processedSql;
@Override
public String getQueryHintString(String sql, List<String> hints) {
processedSql = super.getQueryHintString( sql, hints );
return processedSql;
}
public static String getProcessedSql() {
return processedSql;
}
public static void resetProcessedSql() {
processedSql = "";
}
}
@Entity
public static class Employee {
@Id
@GeneratedValue
public long id;
@ManyToOne
public Department department;
}
@Entity
public static class Department {
@Id
@GeneratedValue
public long id;
public String name;
}
}

View File

@ -1,208 +0,0 @@
/*
* 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.queryhint;
import java.util.List;
import java.util.Map;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Root;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.Query;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Brett Meyer
*/
@RequiresDialect( Oracle8iDialect.class )
public class OracleQueryHintTest extends BaseNonConfigCoreFunctionalTestCase {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
protected void addSettings(Map settings) {
settings.put( AvailableSettings.USE_SQL_COMMENTS, "true" );
sqlStatementInterceptor = new SQLStatementInterceptor( settings );
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Employee.class, Department.class };
}
@Override
protected void afterSessionFactoryBuilt(SessionFactoryImplementor sessionFactory) {
Department department = new Department();
department.name = "Sales";
Employee employee1 = new Employee();
employee1.department = department;
Employee employee2 = new Employee();
employee2.department = department;
doInHibernate( this::sessionFactory, s -> {
s.persist( department );
s.persist( employee1 );
s.persist( employee2 );
} );
}
@Test
public void testQueryHint() {
sqlStatementInterceptor.clear();
// test Query w/ a simple Oracle optimizer hint
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
sqlStatementInterceptor.clear();
// test multiple hints
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.addQueryHint( "USE_CONCAT" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS, USE_CONCAT */" ) );
sqlStatementInterceptor.clear();
// ensure the insertion logic can handle a comment appended to the front
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.setComment( "this is a test" )
.addQueryHint( "ALL_ROWS" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
sqlStatementInterceptor.clear();
// test Criteria
doInHibernate( this::sessionFactory, s -> {
final CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = criteriaBuilder.createQuery( Employee.class );
Root<Employee> root = criteria.from( Employee.class );
Join<Object, Object> departmentJoin = root.join( "department" );
criteria.select( root ).where( criteriaBuilder.equal( departmentJoin.get( "name" ),"Sales" ) );
// Criteria criteria = s.createCriteria( Employee.class )
// .addQueryHint( "ALL_ROWS" )
// .createCriteria( "department" ).add( Restrictions.eq( "name", "Sales" ) );
Query<Employee> query = s.createQuery( criteria );
query.addQueryHint( "ALL_ROWS" );
List results = query.list();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "select /*+ ALL_ROWS */" ) );
sqlStatementInterceptor.clear();
}
@Test
@TestForIssue( jiraKey = "HHH-12362" )
public void testQueryHintAndComment() {
sqlStatementInterceptor.clear();
doInHibernate( this::sessionFactory, s -> {
Query query = s.createQuery( "FROM Employee e WHERE e.department.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setComment( "My_Query" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "/* My_Query */ select /*+ ALL_ROWS */" ) );
sqlStatementInterceptor.clear();
}
@Test
@TestForIssue( jiraKey = "HHH-13608")
public void testQueryHintCaseInsensitive() {
sqlStatementInterceptor.clear();
doInHibernate( this::sessionFactory, s -> {
List results = s.createNativeQuery(
"SELECT e.id as id " +
"FROM Employee e " +
"JOIN Department d ON e.department_id = d.id " +
"WHERE d.name = :departmentName" )
.addQueryHint( "ALL_ROWS" )
.setComment( "My_Query" )
.setParameter( "departmentName", "Sales" )
.getResultList();
assertEquals(results.size(), 2);
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).contains( "/* My_Query */ SELECT /*+ ALL_ROWS */" ) );
sqlStatementInterceptor.clear();
}
@Entity(name = "Employee")
public static class Employee {
@Id
@GeneratedValue
public long id;
@ManyToOne(fetch = FetchType.LAZY)
public Department department;
}
@Entity(name = "Department")
public static class Department {
@Id
@GeneratedValue
public long id;
public String name;
}
}

View File

@ -1,178 +0,0 @@
/*
* 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.queryhint;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Root;
import org.hibernate.query.Query;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Brett Meyer
*/
@RequiresDialect(SQLServer2012Dialect.class)
public class QueryHintSQLServer2012Test extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Employee.class, Department.class };
}
@Override
protected void configure(Configuration configuration) {
configuration.setProperty( AvailableSettings.DIALECT, QueryHintTestSQLServer2012Dialect.class.getName() );
configuration.setProperty( AvailableSettings.USE_SQL_COMMENTS, "true" );
}
@Test
public void testQueryHint() {
Department department = new Department();
department.name = "Sales";
Employee employee1 = new Employee();
employee1.department = department;
Employee employee2 = new Employee();
employee2.department = department;
Session s = openSession();
s.getTransaction().begin();
s.persist( department );
s.persist( employee1 );
s.persist( employee2 );
s.getTransaction().commit();
s.clear();
// test Query w/ a simple SQLServer2012 optimizer hint
s.getTransaction().begin();
Query query = s.createQuery( "FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" ).addQueryHint( "MAXDOP 2" )
.setParameter( "departmentName", "Sales" );
List results = query.list();
s.getTransaction().commit();
s.clear();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "OPTION (MAXDOP 2)" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// test multiple hints
s.getTransaction().begin();
query = s.createQuery( "FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" )
.addQueryHint("MAXDOP 2")
.addQueryHint("CONCAT UNION")
.setParameter("departmentName", "Sales");
results = query.list();
s.getTransaction().commit();
s.clear();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "MAXDOP 2" ) );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "CONCAT UNION" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// ensure the insertion logic can handle a comment appended to the front
s.getTransaction().begin();
query = s.createQuery( "FROM QueryHintSQLServer2012Test$Employee e WHERE e.department.name = :departmentName" ).setComment( "this is a test" )
.addQueryHint( "MAXDOP 2" )
.setParameter( "departmentName", "Sales" );
results = query.list();
s.getTransaction().commit();
s.clear();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "OPTION (MAXDOP 2)" ) );
QueryHintTestSQLServer2012Dialect.resetProcessedSql();
// test Criteria
s.getTransaction().begin();
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = criteriaBuilder.createQuery( Employee.class );
Root<Employee> root = criteria.from( Employee.class );
Join<Object, Object> departement = root.join( "departement", JoinType.INNER );
criteria.select( root ).where( criteriaBuilder.equal( departement.get( "name" ), "Sales" ) );
// Criteria criteria = s.createCriteria( Employee.class ).addQueryHint( "MAXDOP 2" ).createCriteria( "department" )
// .add( Restrictions.eq( "name", "Sales" ) );
// results = criteria.list();
Query<Employee> criteriaQuery = s.createQuery( criteria );
criteriaQuery.addQueryHint( "MAXDOP 2" );
results = criteriaQuery.list();
s.getTransaction().commit();
s.close();
assertEquals( results.size(), 2 );
assertTrue( QueryHintTestSQLServer2012Dialect.getProcessedSql().contains( "OPTION (MAXDOP 2)" ) );
}
/**
* Since the query hint is added to the SQL during Loader's executeQueryStatement -> preprocessSQL, rather than
* early on during the QueryTranslator or QueryLoader initialization, there's not an easy way to check the full SQL
* after completely processing it. Instead, use this ridiculous hack to ensure Loader actually calls Dialect. TODO:
* This is terrible. Better ideas?
*/
public static class QueryHintTestSQLServer2012Dialect extends SQLServer2012Dialect {
private static String processedSql;
@Override
public String getQueryHintString(String sql, List<String> hints) {
processedSql = super.getQueryHintString( sql, hints );
return processedSql;
}
public static String getProcessedSql() {
return processedSql;
}
public static void resetProcessedSql() {
processedSql = "";
}
}
@Entity
public static class Employee {
@Id
@GeneratedValue
public long id;
@ManyToOne
public Department department;
}
@Entity
public static class Department {
@Id
@GeneratedValue
public long id;
public String name;
}
}