Re-enabled additional tests
This commit is contained in:
parent
70c09dfb54
commit
19802edec1
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// $Id: Address.java 7996 2005-08-22 14:49:57Z steveebersole $
|
// $Id: Address.java 7996 2005-08-22 14:49:57Z steveebersole $
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $
|
//$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -9,7 +9,7 @@
|
||||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.querycache">
|
<hibernate-mapping package="org.hibernate.orm.test.querycache">
|
||||||
|
|
||||||
<class name="Course">
|
<class name="Course">
|
||||||
<id name="courseCode">
|
<id name="courseCode">
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $
|
//$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import javax.persistence.EmbeddedId;
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import javax.persistence.EmbeddedId;
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
|
@ -4,32 +4,24 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
|
import org.hibernate.orm.test.querycache.AbstractHqlQueryCacheResultTransformerTest;
|
||||||
|
|
||||||
import org.hibernate.testing.FailureExpected;
|
import org.hibernate.testing.FailureExpected;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public class HqlQueryCacheIgnoreResultTransformerTest extends AbstractQueryCacheResultTransformerTest {
|
public class HqlQueryCacheIgnoreResultTransformerTest extends AbstractHqlQueryCacheResultTransformerTest {
|
||||||
@Override
|
@Override
|
||||||
protected CacheMode getQueryCacheMode() {
|
protected CacheMode getQueryCacheMode() {
|
||||||
return CacheMode.IGNORE;
|
return CacheMode.IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void runTest(HqlExecutor hqlExecutor, CriteriaExecutor criteriaExecutor, ResultChecker checker, boolean isSingleResult)
|
|
||||||
throws Exception {
|
|
||||||
createData();
|
|
||||||
if ( hqlExecutor != null ) {
|
|
||||||
runTest( hqlExecutor, checker, isSingleResult );
|
|
||||||
}
|
|
||||||
deleteData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Override
|
@Override
|
||||||
@FailureExpected( jiraKey = "N/A", message = "HQL query using Transformers.ALIAS_TO_ENTITY_MAP with no projection" )
|
@FailureExpected( jiraKey = "N/A", message = "HQL query using Transformers.ALIAS_TO_ENTITY_MAP with no projection" )
|
||||||
|
@ -53,7 +45,6 @@ public class HqlQueryCacheIgnoreResultTransformerTest extends AbstractQueryCache
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Override
|
@Override
|
||||||
@FailureExpected( jiraKey = "HHH-3345", message = "HQL query using 'select new' and 'join fetch'" )
|
|
||||||
public void testMultiSelectNewMapUsingAliasesWithFetchJoinList() throws Exception {
|
public void testMultiSelectNewMapUsingAliasesWithFetchJoinList() throws Exception {
|
||||||
super.testMultiSelectNewMapUsingAliasesWithFetchJoinList();
|
super.testMultiSelectNewMapUsingAliasesWithFetchJoinList();
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping
|
<hibernate-mapping
|
||||||
package="org.hibernate.test.querycache">
|
package="org.hibernate.orm.test.querycache">
|
||||||
|
|
||||||
<class name="Item" table="Items" batch-size="9">
|
<class name="Item" table="Items" batch-size="9">
|
||||||
<id name="id">
|
<id name="id">
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//$Id: Item.java 9587 2006-03-09 21:38:26Z steve.ebersole@jboss.com $
|
//$Id: Item.java 9587 2006-03-09 21:38:26Z steve.ebersole@jboss.com $
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -4,11 +4,10 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
@ -24,39 +23,36 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.NaturalId;
|
import org.hibernate.annotations.NaturalId;
|
||||||
import org.hibernate.annotations.QueryHints;
|
import org.hibernate.annotations.QueryHints;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
|
||||||
|
|
||||||
import org.hibernate.testing.FailureExpected;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.junit.Test;
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vlad Mihalcea
|
* @author Vlad Mihalcea
|
||||||
*/
|
*/
|
||||||
@TestForIssue(jiraKey = "HHH-12430")
|
@TestForIssue(jiraKey = "HHH-12430")
|
||||||
public class QueryCacheJoinFetchTest extends BaseEntityManagerFunctionalTestCase {
|
@Jpa(
|
||||||
|
annotatedClasses = {
|
||||||
@Override
|
QueryCacheJoinFetchTest.Person.class,
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
QueryCacheJoinFetchTest.Phone.class
|
||||||
return new Class<?>[] {
|
},
|
||||||
Person.class,
|
generateStatistics = true,
|
||||||
Phone.class,
|
integrationSettings = {
|
||||||
};
|
@Setting(name = AvailableSettings.USE_QUERY_CACHE, value = "true"),
|
||||||
}
|
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true")
|
||||||
|
|
||||||
protected void addConfigOptions(Map options) {
|
|
||||||
options.put( AvailableSettings.USE_QUERY_CACHE, "true" );
|
|
||||||
options.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
|
|
||||||
options.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
public class QueryCacheJoinFetchTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected( jiraKey = "HHH-12430" )
|
public void testLifecycle(EntityManagerFactoryScope scope) {
|
||||||
public void testLifecycle() {
|
scope.inTransaction( entityManager -> {
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
|
||||||
Person person = new Person();
|
Person person = new Person();
|
||||||
Phone phone1 = new Phone( "123-456-7890" );
|
Phone phone1 = new Phone( "123-456-7890" );
|
||||||
Phone phone2 = new Phone( "321-654-0987" );
|
Phone phone2 = new Phone( "321-654-0987" );
|
||||||
|
@ -66,10 +62,10 @@ public class QueryCacheJoinFetchTest extends BaseEntityManagerFunctionalTestCase
|
||||||
entityManager.persist( person );
|
entityManager.persist( person );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
entityManagerFactory().getCache().evictAll();
|
scope.getEntityManagerFactory().getCache().evictAll();
|
||||||
entityManagerFactory().unwrap( SessionFactory.class ).getStatistics().clear();
|
scope.getEntityManagerFactory().unwrap( SessionFactory.class ).getStatistics().clear();
|
||||||
|
|
||||||
Person person = doInJPA( this::entityManagerFactory, entityManager -> {
|
Person person = scope.fromEntityManager( entityManager -> {
|
||||||
return entityManager.createQuery(
|
return entityManager.createQuery(
|
||||||
"select distinct p " +
|
"select distinct p " +
|
||||||
"from Person p " +
|
"from Person p " +
|
||||||
|
@ -81,11 +77,11 @@ public class QueryCacheJoinFetchTest extends BaseEntityManagerFunctionalTestCase
|
||||||
assertEquals( 2, person.getPhones().size() );
|
assertEquals( 2, person.getPhones().size() );
|
||||||
assertEquals(
|
assertEquals(
|
||||||
0,
|
0,
|
||||||
entityManagerFactory().unwrap( SessionFactory.class ).getStatistics().getQueryCacheHitCount()
|
scope.getEntityManagerFactory().unwrap( SessionFactory.class ).getStatistics().getQueryCacheHitCount()
|
||||||
);
|
);
|
||||||
|
|
||||||
person = doInJPA( this::entityManagerFactory, entityManager -> {
|
person = scope.fromEntityManager( entityManager -> {
|
||||||
entityManager.getEntityManagerFactory().getCache().evictAll();
|
scope.getEntityManagerFactory().getCache().evictAll();
|
||||||
|
|
||||||
return entityManager.createQuery(
|
return entityManager.createQuery(
|
||||||
"select distinct p " +
|
"select distinct p " +
|
||||||
|
@ -97,7 +93,7 @@ public class QueryCacheJoinFetchTest extends BaseEntityManagerFunctionalTestCase
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
1,
|
1,
|
||||||
entityManagerFactory().unwrap( SessionFactory.class ).getStatistics().getQueryCacheHitCount()
|
scope.getEntityManagerFactory().unwrap( SessionFactory.class ).getStatistics().getQueryCacheHitCount()
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEquals( 2, person.getPhones().size() );
|
assertEquals( 2, person.getPhones().size() );
|
|
@ -0,0 +1,770 @@
|
||||||
|
/*
|
||||||
|
* 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.querycache;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.hibernate.EmptyInterceptor;
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionBuilder;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
import org.hibernate.stat.EntityStatistics;
|
||||||
|
import org.hibernate.stat.QueryStatistics;
|
||||||
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
import org.hibernate.transform.Transformers;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
|
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.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gavin King
|
||||||
|
* @author Brett Meyer
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/querycache/Item.hbm.xml",
|
||||||
|
annotatedClasses = {
|
||||||
|
CompositeKey.class,
|
||||||
|
EntityWithCompositeKey.class,
|
||||||
|
StringCompositeKey.class,
|
||||||
|
EntityWithStringCompositeKey.class
|
||||||
|
},
|
||||||
|
concurrencyStrategy = "nonstrict-read-write"
|
||||||
|
)
|
||||||
|
@SessionFactory(generateStatistics = true)
|
||||||
|
@ServiceRegistry(
|
||||||
|
settings = {
|
||||||
|
@Setting(name = AvailableSettings.USE_QUERY_CACHE, value = "true"),
|
||||||
|
@Setting(name = AvailableSettings.CACHE_REGION_PREFIX, value = "foo"),
|
||||||
|
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class QueryCacheTest {
|
||||||
|
|
||||||
|
private static final CompositeKey PK = new CompositeKey( 1, 2 );
|
||||||
|
private static final ExecutorService executor = Executors.newFixedThreadPool( 4 );
|
||||||
|
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "from java.lang.Object" ).list().forEach( session::remove )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
protected void shutDown() {
|
||||||
|
executor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-5426")
|
||||||
|
public void testInvalidationFromBulkHQL(SessionFactoryScope scope) {
|
||||||
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
|
scope.getSessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
for ( int i = 0; i < 3; i++ ) {
|
||||||
|
Item a = new Item();
|
||||||
|
a.setName( "a" + i );
|
||||||
|
a.setDescription( "a" + i );
|
||||||
|
session.persist( a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
String queryString = "select count(*) from Item";
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// this query will hit the database and create the cache
|
||||||
|
Long result = (Long) session.createQuery( queryString ).setCacheable( true ).uniqueResult();
|
||||||
|
assertEquals( 3, result.intValue() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "delete from Item" ).executeUpdate()
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// and this one SHOULD not be served by the cache
|
||||||
|
Number result2 = (Number) session.createQuery( queryString ).setCacheable( true ).uniqueResult();
|
||||||
|
assertEquals( 0, result2.intValue() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "JBPAPP-4224")
|
||||||
|
public void testHitCacheInSameSession(SessionFactoryScope scope) {
|
||||||
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
|
scope.getSessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
List<Item> list = new ArrayList<>();
|
||||||
|
scope.inSession(
|
||||||
|
session -> {
|
||||||
|
try {
|
||||||
|
session.beginTransaction();
|
||||||
|
for ( int i = 0; i < 3; i++ ) {
|
||||||
|
Item a = new Item();
|
||||||
|
a.setName( "a" + i );
|
||||||
|
a.setDescription( "a" + i );
|
||||||
|
list.add( a );
|
||||||
|
session.persist( a );
|
||||||
|
}
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
// s.close();
|
||||||
|
// s=openSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
String queryString = "from Item";
|
||||||
|
// this query will hit the database and create the cache
|
||||||
|
session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
//and this one SHOULD served by the cache
|
||||||
|
session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
QueryStatistics qs = session.getSessionFactory()
|
||||||
|
.getStatistics()
|
||||||
|
.getQueryStatistics( queryString );
|
||||||
|
assertEquals( 1, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 1, qs.getCachePutCount() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( session.getTransaction().isActive() ) {
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
for ( Object obj : list ) {
|
||||||
|
session.delete( obj );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String queryString = "from Item i where i.name='widget'";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQueryCacheInvalidation(SessionFactoryScope scope) throws Exception {
|
||||||
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
|
||||||
|
final String queryString = "from Item i where i.name='widget'";
|
||||||
|
|
||||||
|
final QueryStatistics qs = statistics.getQueryStatistics( queryString );
|
||||||
|
final EntityStatistics es = statistics.getEntityStatistics( Item.class.getName() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
Item i = new Item();
|
||||||
|
i.setName( "widget" );
|
||||||
|
i.setDescription( "A really top-quality, full-featured widget." );
|
||||||
|
session.save( i );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// hit -> 0
|
||||||
|
// miss -> 1
|
||||||
|
// put -> 1
|
||||||
|
|
||||||
|
assertEquals( 1, es.getInsertCount() );
|
||||||
|
assertEquals( 0, es.getUpdateCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getQueryCacheHitCount() );
|
||||||
|
assertEquals( 0, qs.getCacheHitCount() );
|
||||||
|
|
||||||
|
assertEquals( 1, statistics.getQueryCacheMissCount() );
|
||||||
|
assertEquals( 1, qs.getCacheMissCount() );
|
||||||
|
|
||||||
|
assertEquals( 1, statistics.getQueryCachePutCount() );
|
||||||
|
assertEquals( 1, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
assertEquals( 1, statistics.getQueryExecutionCount() );
|
||||||
|
assertEquals( 1, qs.getExecutionCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List<Item> result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// hit -> 0
|
||||||
|
// miss -> 2
|
||||||
|
// put -> 2
|
||||||
|
|
||||||
|
assertEquals( 1, es.getInsertCount() );
|
||||||
|
assertEquals( 0, es.getUpdateCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getQueryCacheHitCount() );
|
||||||
|
assertEquals( 0, qs.getCacheHitCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCachePutCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryExecutionCount() );
|
||||||
|
assertEquals( 2, qs.getExecutionCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// hit -> 1
|
||||||
|
// miss -> 2
|
||||||
|
// put -> 2
|
||||||
|
|
||||||
|
assertEquals( 1, es.getInsertCount() );
|
||||||
|
assertEquals( 0, es.getUpdateCount() );
|
||||||
|
|
||||||
|
assertEquals( 1, statistics.getQueryCacheHitCount() );
|
||||||
|
assertEquals( 1, qs.getCacheHitCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCachePutCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryExecutionCount() );
|
||||||
|
assertEquals( 2, qs.getExecutionCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
|
||||||
|
assertEquals( 1, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
|
||||||
|
Item item = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
List<Item> result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
Item i = result.get( 0 );
|
||||||
|
assertTrue( Hibernate.isInitialized( i ) );
|
||||||
|
assertTrue( session.contains( i ) );
|
||||||
|
i.setName( "Widget" );
|
||||||
|
session.flush();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// hit -> 2
|
||||||
|
// miss -> 2
|
||||||
|
// put -> 2
|
||||||
|
//
|
||||||
|
// + another invalidation
|
||||||
|
|
||||||
|
assertEquals( 1, es.getInsertCount() );
|
||||||
|
assertEquals( 1, es.getUpdateCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCacheHitCount() );
|
||||||
|
assertEquals( 2, qs.getCacheHitCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCachePutCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryExecutionCount() );
|
||||||
|
assertEquals( 2, qs.getExecutionCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
|
||||||
|
|
||||||
|
Thread.sleep( 200 );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
Item i = session.get( Item.class, item.getId() );
|
||||||
|
|
||||||
|
session.delete( i );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// hit -> 2
|
||||||
|
// miss -> 3
|
||||||
|
// put -> 3
|
||||||
|
|
||||||
|
assertEquals( 1, es.getInsertCount() );
|
||||||
|
assertEquals( 1, es.getUpdateCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, statistics.getQueryCacheHitCount() );
|
||||||
|
assertEquals( 2, qs.getCacheHitCount() );
|
||||||
|
|
||||||
|
assertEquals( 3, statistics.getQueryCacheMissCount() );
|
||||||
|
assertEquals( 3, qs.getCacheMissCount() );
|
||||||
|
|
||||||
|
assertEquals( 3, statistics.getQueryCachePutCount() );
|
||||||
|
assertEquals( 3, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
assertEquals( 3, statistics.getQueryExecutionCount() );
|
||||||
|
assertEquals( 3, qs.getExecutionCount() );
|
||||||
|
|
||||||
|
assertEquals( 0, statistics.getEntityFetchCount() );
|
||||||
|
assertEquals( 0, es.getFetchCount() );
|
||||||
|
|
||||||
|
assertEquals( 2, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 3, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 3, qs.getCachePutCount() );
|
||||||
|
assertEquals( 3, qs.getExecutionCount() );
|
||||||
|
assertEquals( 0, es.getFetchCount() ); //check that it was being cached
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresDialectFeature(
|
||||||
|
feature = DialectFeatureChecks.CaseSensitiveCheck.class,
|
||||||
|
comment = "i.name='widget' should not match on case sensitive database."
|
||||||
|
)
|
||||||
|
public void testCaseInsensitiveComparison(SessionFactoryScope scope) {
|
||||||
|
Item item = new Item();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
item.setName( "Widget" );
|
||||||
|
item.setDescription( "A really top-quality, full-featured widget." );
|
||||||
|
session.save( item );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
Item i = session.get( Item.class, item.getId() );
|
||||||
|
assertEquals( "Widget", i.getName() );
|
||||||
|
session.delete( i );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProjectionCache(SessionFactoryScope scope) throws Exception {
|
||||||
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
|
scope.getSessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
final String queryString = "select i.description as desc from Item i where i.name='widget'";
|
||||||
|
|
||||||
|
Item item = new Item();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
item.setName( "widget" );
|
||||||
|
item.setDescription( "A really top-quality, full-featured widget." );
|
||||||
|
session.save( item );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
QueryStatistics qs = scope.getSessionFactory().getStatistics().getQueryStatistics( queryString );
|
||||||
|
EntityStatistics es = scope.getSessionFactory().getStatistics().getEntityStatistics( Item.class.getName() );
|
||||||
|
|
||||||
|
assertEquals( 0, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 1, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 1, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
Thread.sleep( 200 );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
assertEquals( item.getDescription(), result.get( 0 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals( 0, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
assertEquals( item.getDescription(), result.get( 0 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals( 1, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString )
|
||||||
|
.setCacheable( true )
|
||||||
|
.setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP )
|
||||||
|
.list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
Map m = (Map) result.get( 0 );
|
||||||
|
assertEquals( 1, m.size() );
|
||||||
|
assertEquals( item.getDescription(), m.get( "desc" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
2,
|
||||||
|
qs.getCacheHitCount(),
|
||||||
|
"hit count should go up since data is not transformed until after it is cached"
|
||||||
|
);
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString )
|
||||||
|
.setCacheable( true )
|
||||||
|
.setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP )
|
||||||
|
.list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
Map m = (Map) result.get( 0 );
|
||||||
|
assertEquals( 1, m.size() );
|
||||||
|
assertEquals( item.getDescription(), m.get( "desc" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
qs.getCacheHitCount(),
|
||||||
|
"hit count should go up since data is not transformed until after it is cachedr"
|
||||||
|
);
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
assertTrue( Hibernate.isInitialized( result.get( 0 ) ) );
|
||||||
|
Item i = session.get( Item.class, item.getId() );
|
||||||
|
i.setName( "widget" );
|
||||||
|
i.setDescription( "A middle-quality widget." );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals( 4, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 2, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 2, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
Thread.sleep( 200 );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
|
assertEquals( 1, result.size() );
|
||||||
|
Item i = session.get( Item.class, item.getId() );
|
||||||
|
assertEquals( "A middle-quality widget.", result.get( 0 ) );
|
||||||
|
|
||||||
|
assertEquals( 4, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 3, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 3, qs.getCachePutCount() );
|
||||||
|
|
||||||
|
session.delete( i );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals( 4, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 3, qs.getCacheMissCount() );
|
||||||
|
assertEquals( 3, qs.getCachePutCount() );
|
||||||
|
assertEquals( 3, qs.getExecutionCount() );
|
||||||
|
assertEquals( 0, es.getFetchCount() ); //check that it was being cached
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-4459")
|
||||||
|
public void testGetByCompositeId(SessionFactoryScope scope) {
|
||||||
|
|
||||||
|
scope.inSession(
|
||||||
|
session -> {
|
||||||
|
session.beginTransaction();
|
||||||
|
try {
|
||||||
|
session.persist( new EntityWithCompositeKey( PK ) );
|
||||||
|
Query query = session.createQuery( "FROM EntityWithCompositeKey e WHERE e.pk = :pk" );
|
||||||
|
query.setCacheable( true );
|
||||||
|
query.setParameter( "pk", PK );
|
||||||
|
assertEquals( 1, query.list().size() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inSession(
|
||||||
|
session -> {
|
||||||
|
session.beginTransaction();
|
||||||
|
try {
|
||||||
|
EntityWithStringCompositeKey entity = new EntityWithStringCompositeKey();
|
||||||
|
StringCompositeKey key = new StringCompositeKey();
|
||||||
|
key.setAnalog( "foo1" );
|
||||||
|
key.setDevice( "foo2" );
|
||||||
|
key.setDeviceType( "foo3" );
|
||||||
|
key.setSubstation( "foo4" );
|
||||||
|
entity.setPk( key );
|
||||||
|
session.persist( entity );
|
||||||
|
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<EntityWithStringCompositeKey> criteria = criteriaBuilder.createQuery(
|
||||||
|
EntityWithStringCompositeKey.class );
|
||||||
|
Root<EntityWithStringCompositeKey> root = criteria.from( EntityWithStringCompositeKey.class );
|
||||||
|
criteria.where( criteriaBuilder.equal( root.get( "pk" ), key ) );
|
||||||
|
session.createQuery( criteria ).setCacheable( true );
|
||||||
|
|
||||||
|
assertEquals( 1, session.createQuery( criteria ).list().size() );
|
||||||
|
// Criteria c = s.createCriteria(
|
||||||
|
// EntityWithStringCompositeKey.class ).add( Restrictions.eq(
|
||||||
|
// "pk", key ) );
|
||||||
|
// c.setCacheable( true );
|
||||||
|
// assertEquals( 1, c.list().size() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-3051")
|
||||||
|
public void testScalarSQLQuery(SessionFactoryScope scope) {
|
||||||
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
|
scope.getSessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
Item item = new Item();
|
||||||
|
item.setName( "fooName" );
|
||||||
|
item.setDescription( "fooDescription" );
|
||||||
|
session.persist( item );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// Note: StandardQueryCache#put handles single results and multiple results differently. So, test both
|
||||||
|
// 1 and 2+ scalars.
|
||||||
|
|
||||||
|
String sqlQuery = "select name, description from Items";
|
||||||
|
NativeQuery query = session.createNativeQuery( sqlQuery );
|
||||||
|
query.setCacheable( true );
|
||||||
|
query.addScalar( "name" );
|
||||||
|
query.addScalar( "description" );
|
||||||
|
Object[] result1 = (Object[]) query.uniqueResult();
|
||||||
|
assertNotNull( result1 );
|
||||||
|
assertEquals( 2, result1.length );
|
||||||
|
assertEquals( "fooName", result1[0] );
|
||||||
|
assertEquals( "fooDescription", result1[1] );
|
||||||
|
|
||||||
|
sqlQuery = "select name from Items";
|
||||||
|
query = session.createNativeQuery( sqlQuery );
|
||||||
|
query.setCacheable( true );
|
||||||
|
query.addScalar( "name" );
|
||||||
|
String result2 = (String) query.uniqueResult();
|
||||||
|
assertNotNull( result2 );
|
||||||
|
assertEquals( "fooName", result2 );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// public void testGetByCompositeIdNoCache() {
|
||||||
|
// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e.pk = :pk");
|
||||||
|
// query.setParameter("pk", PK);
|
||||||
|
// assertEquals(1, query.getResultList().size());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void testGetByEntityIself() {
|
||||||
|
// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e = :ent");
|
||||||
|
// query.setParameter("ent", new EntityWithCompositeKey(PK));
|
||||||
|
// assertEquals(1, query.getResultList().size());
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-9962")
|
||||||
|
/* Test courtesy of Giambattista Bloisi */
|
||||||
|
public void testDelayedLoad(SessionFactoryScope scope) throws InterruptedException, ExecutionException {
|
||||||
|
DelayLoadOperations interceptor = new DelayLoadOperations();
|
||||||
|
final SessionBuilder sessionBuilder = scope.getSessionFactory().withOptions().interceptor( interceptor );
|
||||||
|
Item item1 = new Item();
|
||||||
|
item1.setName( "Item1" );
|
||||||
|
item1.setDescription( "Washington" );
|
||||||
|
|
||||||
|
try (Session s1 = sessionBuilder.openSession()) {
|
||||||
|
Transaction tx1 = s1.beginTransaction();
|
||||||
|
try {
|
||||||
|
s1.persist( item1 );
|
||||||
|
tx1.commit();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( tx1.isActive() ) {
|
||||||
|
tx1.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item2 = new Item();
|
||||||
|
item2.setName( "Item2" );
|
||||||
|
item2.setDescription( "Chicago" );
|
||||||
|
try (Session s2 = sessionBuilder.openSession()) {
|
||||||
|
Transaction tx2 = s2.beginTransaction();
|
||||||
|
try {
|
||||||
|
s2.persist( item2 );
|
||||||
|
tx2.commit();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( tx2.isActive() ) {
|
||||||
|
tx2.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor.blockOnLoad();
|
||||||
|
|
||||||
|
Future<Item> fetchedItem = executor.submit( () -> findByDescription( sessionBuilder, "Washington" ) );
|
||||||
|
|
||||||
|
// wait for the onLoad listener to be called
|
||||||
|
interceptor.waitOnLoad();
|
||||||
|
|
||||||
|
try (Session s3 = sessionBuilder.openSession()) {
|
||||||
|
Transaction tx3 = s3.beginTransaction();
|
||||||
|
try {
|
||||||
|
item1.setDescription( "New York" );
|
||||||
|
item2.setDescription( "Washington" );
|
||||||
|
s3.update( item1 );
|
||||||
|
s3.update( item2 );
|
||||||
|
tx3.commit();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( tx3.isActive() ) {
|
||||||
|
tx3.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor.unblockOnLoad();
|
||||||
|
|
||||||
|
// the concurrent query was executed before the data was amended so
|
||||||
|
// let's expect "Item1" to be returned as living in Washington
|
||||||
|
Item fetched = fetchedItem.get();
|
||||||
|
assertEquals( "Item1", fetched.getName() );
|
||||||
|
|
||||||
|
// Query again: now "Item2" is expected to live in Washington
|
||||||
|
fetched = findByDescription( sessionBuilder, "Washington" );
|
||||||
|
assertEquals( "Item2", fetched.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Item findByDescription(SessionBuilder sessionBuilder, final String description) {
|
||||||
|
try (Session s = sessionBuilder.openSession()) {
|
||||||
|
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Item> criteria = criteriaBuilder.createQuery( Item.class );
|
||||||
|
Root<Item> root = criteria.from( Item.class );
|
||||||
|
criteria.where( criteriaBuilder.equal( root.get( "description" ), description ) );
|
||||||
|
|
||||||
|
return s.createQuery( criteria ).setCacheable( true ).setReadOnly( true ).uniqueResult();
|
||||||
|
// return (Item) s.createCriteria(Item.class)
|
||||||
|
// .setCacheable(true)
|
||||||
|
// .setReadOnly(true)
|
||||||
|
// .add(Restrictions.eq("description", description))
|
||||||
|
// .uniqueResult();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DelayLoadOperations extends EmptyInterceptor {
|
||||||
|
|
||||||
|
private volatile CountDownLatch blockLatch;
|
||||||
|
private volatile CountDownLatch waitLatch;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
|
||||||
|
// Synchronize load and update activities
|
||||||
|
try {
|
||||||
|
if ( waitLatch != null ) {
|
||||||
|
waitLatch.countDown();
|
||||||
|
}
|
||||||
|
if ( blockLatch != null ) {
|
||||||
|
blockLatch.await();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void blockOnLoad() {
|
||||||
|
blockLatch = new CountDownLatch( 1 );
|
||||||
|
waitLatch = new CountDownLatch( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitOnLoad() throws InterruptedException {
|
||||||
|
waitLatch.await();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unblockOnLoad() {
|
||||||
|
if ( blockLatch != null ) {
|
||||||
|
blockLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
|
@ -4,11 +4,10 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
@ -20,72 +19,72 @@ import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.junit.Test;
|
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.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vlad Mihalceca
|
* @author Vlad Mihalceca
|
||||||
*/
|
*/
|
||||||
@TestForIssue( jiraKey = "HHH-12107" )
|
@TestForIssue( jiraKey = "HHH-12107" )
|
||||||
public class StructuredQueryCacheTest extends BaseNonConfigCoreFunctionalTestCase {
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
StructuredQueryCacheTest.OneToManyWithEmbeddedId.class,
|
||||||
|
StructuredQueryCacheTest.OneToManyWithEmbeddedIdChild.class,
|
||||||
|
StructuredQueryCacheTest.OneToManyWithEmbeddedIdKey.class
|
||||||
|
},
|
||||||
|
concurrencyStrategy = "transactional"
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
@ServiceRegistry(settings = {
|
||||||
|
@Setting( name = AvailableSettings.USE_QUERY_CACHE, value = "true" ),
|
||||||
|
@Setting( name = AvailableSettings.CACHE_REGION_PREFIX, value = "foo" ),
|
||||||
|
@Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true" ),
|
||||||
|
@Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ),
|
||||||
|
@Setting( name = AvailableSettings.USE_STRUCTURED_CACHE, value = "true" ),
|
||||||
|
})
|
||||||
|
public class StructuredQueryCacheTest {
|
||||||
|
|
||||||
@Override
|
@AfterEach
|
||||||
protected Class[] getAnnotatedClasses() {
|
public void tearDown(SessionFactoryScope scope){
|
||||||
return new Class[] {
|
scope.inTransaction(
|
||||||
OneToManyWithEmbeddedId.class,
|
session -> {
|
||||||
OneToManyWithEmbeddedIdChild.class,
|
session.createQuery( "delete from OneToManyWithEmbeddedIdChild" ).executeUpdate();
|
||||||
OneToManyWithEmbeddedIdKey.class
|
session.createQuery( "delete from OneToManyWithEmbeddedId" ).executeUpdate();
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
@Override
|
|
||||||
protected void addSettings(Map settings) {
|
|
||||||
settings.put( AvailableSettings.USE_QUERY_CACHE, "true" );
|
|
||||||
settings.put( AvailableSettings.CACHE_REGION_PREFIX, "foo" );
|
|
||||||
settings.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
|
|
||||||
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
|
||||||
settings.put( AvailableSettings.USE_STRUCTURED_CACHE, "true" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getCacheConcurrencyStrategy() {
|
|
||||||
return "transactional";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-12107" )
|
@TestForIssue( jiraKey = "HHH-12107" )
|
||||||
public void testEmbeddedIdInOneToMany() {
|
public void testEmbeddedIdInOneToMany(SessionFactoryScope scope) {
|
||||||
|
|
||||||
OneToManyWithEmbeddedIdKey key = new OneToManyWithEmbeddedIdKey( 1234 );
|
OneToManyWithEmbeddedIdKey key = new OneToManyWithEmbeddedIdKey( 1234 );
|
||||||
final OneToManyWithEmbeddedId o = new OneToManyWithEmbeddedId( key );
|
final OneToManyWithEmbeddedId o = new OneToManyWithEmbeddedId( key );
|
||||||
o.setItems( new HashSet<>() );
|
o.setItems( new HashSet<>() );
|
||||||
o.getItems().add( new OneToManyWithEmbeddedIdChild( 1 ) );
|
o.getItems().add( new OneToManyWithEmbeddedIdChild( 1 ) );
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session ->
|
||||||
session.persist( o );
|
session.persist( o )
|
||||||
});
|
);
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session -> {
|
||||||
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
||||||
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
||||||
assertNotNull( _entity );
|
assertNotNull( _entity );
|
||||||
});
|
});
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session -> {
|
||||||
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
||||||
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
||||||
assertNotNull( _entity );
|
assertNotNull( _entity );
|
||||||
|
@ -97,6 +96,8 @@ public class StructuredQueryCacheTest extends BaseNonConfigCoreFunctionalTestCas
|
||||||
|
|
||||||
private OneToManyWithEmbeddedIdKey id;
|
private OneToManyWithEmbeddedIdKey id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
private Set<OneToManyWithEmbeddedIdChild> items = new HashSet<>( );
|
private Set<OneToManyWithEmbeddedIdChild> items = new HashSet<>( );
|
||||||
|
|
||||||
public OneToManyWithEmbeddedId() {
|
public OneToManyWithEmbeddedId() {
|
||||||
|
@ -130,6 +131,8 @@ public class StructuredQueryCacheTest extends BaseNonConfigCoreFunctionalTestCas
|
||||||
public static class OneToManyWithEmbeddedIdChild {
|
public static class OneToManyWithEmbeddedIdChild {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
|
||||||
public OneToManyWithEmbeddedIdChild() {
|
public OneToManyWithEmbeddedIdChild() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +149,14 @@ public class StructuredQueryCacheTest extends BaseNonConfigCoreFunctionalTestCas
|
||||||
public void setId(int id) {
|
public void setId(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Embeddable
|
@Embeddable
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $
|
//$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
|
@ -9,7 +9,7 @@
|
||||||
* Created on 28-Jan-2005
|
* Created on 28-Jan-2005
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.querycache;
|
package org.hibernate.orm.test.querycache;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
File diff suppressed because it is too large
Load Diff
|
@ -17,17 +17,4 @@ public class CriteriaQueryCacheIgnoreResultTransformerTest extends AbstractQuery
|
||||||
return CacheMode.IGNORE;
|
return CacheMode.IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void runTest(HqlExecutor hqlExecutor, CriteriaExecutor criteriaExecutor, ResultChecker checker, boolean isSingleResult)
|
|
||||||
throws Exception {
|
|
||||||
createData();
|
|
||||||
try {
|
|
||||||
if ( criteriaExecutor != null ) {
|
|
||||||
runTest( criteriaExecutor, checker, isSingleResult );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
deleteData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,789 +1,108 @@
|
||||||
/*
|
|
||||||
* 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.querycache;
|
package org.hibernate.test.querycache;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
|
|
||||||
import org.hibernate.EmptyInterceptor;
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.query.NativeQuery;
|
|
||||||
import org.hibernate.query.Query;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.SessionBuilder;
|
|
||||||
import org.hibernate.Transaction;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.stat.EntityStatistics;
|
import org.hibernate.orm.test.querycache.CompositeKey;
|
||||||
|
import org.hibernate.orm.test.querycache.EntityWithCompositeKey;
|
||||||
|
import org.hibernate.orm.test.querycache.EntityWithStringCompositeKey;
|
||||||
|
import org.hibernate.orm.test.querycache.Item;
|
||||||
|
import org.hibernate.orm.test.querycache.StringCompositeKey;
|
||||||
import org.hibernate.stat.QueryStatistics;
|
import org.hibernate.stat.QueryStatistics;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
|
||||||
import org.hibernate.transform.Transformers;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.Test;
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
@DomainModel(
|
||||||
* @author Gavin King
|
xmlMappings = "org/hibernate/orm/test/querycache/Item.hbm.xml",
|
||||||
* @author Brett Meyer
|
annotatedClasses = {
|
||||||
*/
|
|
||||||
public class QueryCacheTest extends BaseNonConfigCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
private static final CompositeKey PK = new CompositeKey(1, 2);
|
|
||||||
private static final ExecutorService executor = Executors.newFixedThreadPool(4);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "querycache/Item.hbm.xml" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
CompositeKey.class,
|
CompositeKey.class,
|
||||||
EntityWithCompositeKey.class,
|
EntityWithCompositeKey.class,
|
||||||
StringCompositeKey.class,
|
StringCompositeKey.class,
|
||||||
EntityWithStringCompositeKey.class
|
EntityWithStringCompositeKey.class
|
||||||
};
|
},
|
||||||
}
|
concurrencyStrategy = "nonstrict-read-write"
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addSettings(Map settings) {
|
|
||||||
settings.put( AvailableSettings.USE_QUERY_CACHE, "true" );
|
|
||||||
settings.put( AvailableSettings.CACHE_REGION_PREFIX, "foo" );
|
|
||||||
settings.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
|
|
||||||
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void shutDown() {
|
|
||||||
super.shutDown();
|
|
||||||
executor.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getCacheConcurrencyStrategy() {
|
|
||||||
return "nonstrict-read-write";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-5426" )
|
|
||||||
public void testInvalidationFromBulkHQL() {
|
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
List list = new ArrayList();
|
|
||||||
s.beginTransaction();
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
Item a = new Item();
|
|
||||||
a.setName("a" + i);
|
|
||||||
a.setDescription("a" + i);
|
|
||||||
list.add(a);
|
|
||||||
s.persist(a);
|
|
||||||
}
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
String queryString = "select count(*) from Item";
|
|
||||||
// this query will hit the database and create the cache
|
|
||||||
Long result = (Long) s.createQuery(queryString).setCacheable(true).uniqueResult();
|
|
||||||
assertEquals(3, result.intValue());
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
String updateString = "delete from Item";
|
|
||||||
s.createQuery(updateString).executeUpdate();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
// and this one SHOULD not be served by the cache
|
|
||||||
Number result2 = (Number) s.createQuery(queryString).setCacheable(true).uniqueResult();
|
|
||||||
assertEquals(0, result2.intValue());
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "JBPAPP-4224" )
|
|
||||||
public void testHitCacheInSameSession() {
|
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
Session s = openSession();
|
|
||||||
List list = new ArrayList();
|
|
||||||
s.beginTransaction();
|
|
||||||
for ( int i = 0; i < 3; i++ ) {
|
|
||||||
Item a = new Item();
|
|
||||||
a.setName( "a" + i );
|
|
||||||
a.setDescription( "a" + i );
|
|
||||||
list.add( a );
|
|
||||||
s.persist( a );
|
|
||||||
}
|
|
||||||
s.getTransaction().commit();
|
|
||||||
|
|
||||||
// s.close();
|
|
||||||
// s=openSession();
|
|
||||||
|
|
||||||
s.beginTransaction();
|
|
||||||
String queryString = "from Item";
|
|
||||||
// this query will hit the database and create the cache
|
|
||||||
s.createQuery( queryString ).setCacheable( true ).list();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
|
|
||||||
s.beginTransaction();
|
|
||||||
//and this one SHOULD served by the cache
|
|
||||||
s.createQuery( queryString ).setCacheable( true ).list();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
QueryStatistics qs = s.getSessionFactory().getStatistics().getQueryStatistics( queryString );
|
|
||||||
assertEquals( 1, qs.getCacheHitCount() );
|
|
||||||
assertEquals( 1, qs.getCachePutCount() );
|
|
||||||
s.close();
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
for(Object obj:list){
|
|
||||||
s.delete( obj );
|
|
||||||
}
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String queryString = "from Item i where i.name='widget'";
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryCacheInvalidation() throws Exception {
|
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
|
||||||
|
|
||||||
final StatisticsImplementor statistics = sessionFactory().getStatistics();
|
|
||||||
statistics.clear();
|
|
||||||
|
|
||||||
final String queryString = "from Item i where i.name='widget'";
|
|
||||||
|
|
||||||
final QueryStatistics qs = statistics.getQueryStatistics( queryString );
|
|
||||||
final EntityStatistics es = statistics.getEntityStatistics( Item.class.getName() );
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
Item i = new Item();
|
|
||||||
i.setName("widget");
|
|
||||||
i.setDescription("A really top-quality, full-featured widget.");
|
|
||||||
s.save(i);
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
// hit -> 0
|
|
||||||
// miss -> 1
|
|
||||||
// put -> 1
|
|
||||||
|
|
||||||
assertEquals( es.getInsertCount(), 1 );
|
|
||||||
assertEquals( es.getUpdateCount(), 0 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheHitCount(), 0 );
|
|
||||||
assertEquals( qs.getCacheHitCount(), 0 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheMissCount(), 1 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 1);
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCachePutCount(), 1 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 1);
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryExecutionCount(), 1 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 1 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
List result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
// hit -> 0
|
|
||||||
// miss -> 2
|
|
||||||
// put -> 2
|
|
||||||
|
|
||||||
assertEquals( es.getInsertCount(), 1 );
|
|
||||||
assertEquals( es.getUpdateCount(), 0 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheHitCount(), 0 );
|
|
||||||
assertEquals( qs.getCacheHitCount(), 0 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCachePutCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryExecutionCount(), 2 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
// hit -> 1
|
|
||||||
// miss -> 2
|
|
||||||
// put -> 2
|
|
||||||
|
|
||||||
assertEquals( es.getInsertCount(), 1 );
|
|
||||||
assertEquals( es.getUpdateCount(), 0 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheHitCount(), 1 );
|
|
||||||
assertEquals( qs.getCacheHitCount(), 1);
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCachePutCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryExecutionCount(), 2 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 1 );
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
i = (Item) result.get(0);
|
|
||||||
assertTrue( Hibernate.isInitialized( i ) );
|
|
||||||
assertTrue( s.contains( i ) );
|
|
||||||
i.setName("Widget");
|
|
||||||
s.flush();
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
// hit -> 2
|
|
||||||
// miss -> 2
|
|
||||||
// put -> 2
|
|
||||||
//
|
|
||||||
// + another invalidation
|
|
||||||
|
|
||||||
assertEquals( es.getInsertCount(), 1 );
|
|
||||||
assertEquals( es.getUpdateCount(), 1 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheHitCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheHitCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCachePutCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryExecutionCount(), 2 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
i = (Item) s.get( Item.class, new Long(i.getId()) );
|
|
||||||
|
|
||||||
s.delete(i);
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
// hit -> 2
|
|
||||||
// miss -> 3
|
|
||||||
// put -> 3
|
|
||||||
|
|
||||||
|
|
||||||
assertEquals( es.getInsertCount(), 1 );
|
|
||||||
assertEquals( es.getUpdateCount(), 1 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheHitCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheHitCount(), 2 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCacheMissCount(), 3 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 3 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryCachePutCount(), 3);
|
|
||||||
assertEquals( qs.getCachePutCount(), 3 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getQueryExecutionCount(), 3);
|
|
||||||
assertEquals( qs.getExecutionCount(), 3 );
|
|
||||||
|
|
||||||
assertEquals( statistics.getEntityFetchCount(), 0 );
|
|
||||||
assertEquals( es.getFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 3 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 3 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 3 );
|
|
||||||
assertEquals( es.getFetchCount(), 0 ); //check that it was being cached
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@RequiresDialectFeature(
|
|
||||||
value = DialectChecks.CaseSensitiveCheck.class,
|
|
||||||
comment = "i.name='widget' should not match on case sensitive database."
|
|
||||||
)
|
)
|
||||||
public void testCaseInsensitiveComparison() {
|
@SessionFactory(generateStatistics = true)
|
||||||
Session s = openSession();
|
@ServiceRegistry(
|
||||||
s.beginTransaction();
|
settings = {
|
||||||
Item i = new Item();
|
@Setting(name = AvailableSettings.USE_QUERY_CACHE, value = "true"),
|
||||||
i.setName( "Widget" );
|
@Setting(name = AvailableSettings.CACHE_REGION_PREFIX, value = "foo"),
|
||||||
i.setDescription( "A really top-quality, full-featured widget." );
|
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true")
|
||||||
s.save( i );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
List result = s.createQuery( queryString ).list();
|
|
||||||
assertEquals(1, result.size());
|
|
||||||
i = (Item) s.get( Item.class, new Long(i.getId()) );
|
|
||||||
assertEquals( i.getName(), "Widget" );
|
|
||||||
s.delete(i);
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
public class QueryCacheTest {
|
||||||
|
|
||||||
|
/*
|
||||||
|
All the other tests of QueryCacheTest have been already moved into org.hibernate.orm test paxkage
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testQueryCacheFetch() throws Exception {
|
public void testQueryCacheFetch(SessionFactoryScope scope) throws Exception {
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
scope.getSessionFactory().getCache().evictQueryRegions();
|
||||||
sessionFactory().getStatistics().clear();
|
scope.getSessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
// persist our 2 items. This saves them to the db, but also into the second level entity cache region
|
// persist our 2 items. This saves them to the db, but also into the second level entity cache region
|
||||||
Session s = openSession();
|
scope.inTransaction(
|
||||||
Transaction t = s.beginTransaction();
|
session -> {
|
||||||
Item i = new Item();
|
Item i = new Item();
|
||||||
i.setName( "widget" );
|
i.setName( "widget" );
|
||||||
i.setDescription( "A really top-quality, full-featured widget." );
|
i.setDescription( "A really top-quality, full-featured widget." );
|
||||||
Item i2 = new Item();
|
Item i2 = new Item();
|
||||||
i2.setName( "other widget" );
|
i2.setName( "other widget" );
|
||||||
i2.setDescription( "Another decent widget." );
|
i2.setDescription( "Another decent widget." );
|
||||||
s.persist(i);
|
session.persist( i );
|
||||||
s.persist(i2);
|
session.persist( i2 );
|
||||||
t.commit();
|
}
|
||||||
s.close();
|
);
|
||||||
|
|
||||||
final String queryString = "from Item i where i.name like '%widget'";
|
final String queryString = "from Item i where i.name like '%widget'";
|
||||||
|
|
||||||
QueryStatistics qs = s.getSessionFactory().getStatistics().getQueryStatistics( queryString );
|
QueryStatistics qs = scope.getSessionFactory().getStatistics().getQueryStatistics( queryString );
|
||||||
|
|
||||||
Thread.sleep( 200 );
|
Thread.sleep( 200 );
|
||||||
|
|
||||||
// perform the cacheable query. this will execute the query (no query cache hit), but the Items will be
|
// perform the cacheable query. this will execute the query (no query cache hit), but the Items will be
|
||||||
// found in second level entity cache region
|
// found in second level entity cache region
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
t = s.beginTransaction();
|
session -> {
|
||||||
List result = s.createQuery( queryString ).setCacheable( true ).list();
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
assertEquals( result.size(), 2 );
|
assertEquals( 2, result.size() );
|
||||||
t.commit();
|
}
|
||||||
s.close();
|
);
|
||||||
assertEquals( qs.getCacheHitCount(), 0 );
|
|
||||||
assertEquals( s.getSessionFactory().getStatistics().getEntityFetchCount(), 0 );
|
|
||||||
|
|
||||||
|
assertEquals( 0, qs.getCacheHitCount() );
|
||||||
|
assertEquals( 0, scope.getSessionFactory().getStatistics().getEntityFetchCount() );
|
||||||
|
|
||||||
// evict the Items from the second level entity cache region
|
// evict the Items from the second level entity cache region
|
||||||
sessionFactory().getCache().evictEntityRegion( Item.class );
|
scope.getSessionFactory().getCache().evictEntityRegion( Item.class );
|
||||||
|
|
||||||
// now, perform the cacheable query again. this time we should not execute the query (query cache hit).
|
// now, perform the cacheable query again. this time we should not execute the query (query cache hit).
|
||||||
// However, the Items will not be found in second level entity cache region this time (we evicted them above)
|
// However, the Items will not be found in second level entity cache region this time (we evicted them above)
|
||||||
// nor are they in associated with the session.
|
// nor are they in associated with the session.
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
t = s.beginTransaction();
|
session -> {
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
List result = session.createQuery( queryString ).setCacheable( true ).list();
|
||||||
assertEquals( result.size(), 2 );
|
assertEquals( 2, result.size() );
|
||||||
assertTrue( Hibernate.isInitialized( result.get( 0 ) ) );
|
assertTrue( Hibernate.isInitialized( result.get( 0 ) ) );
|
||||||
assertTrue( Hibernate.isInitialized( result.get( 1 ) ) );
|
assertTrue( Hibernate.isInitialized( result.get( 1 ) ) );
|
||||||
t.commit();
|
}
|
||||||
s.close();
|
);
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 1 );
|
assertEquals( 1, qs.getCacheHitCount() );
|
||||||
assertEquals( s.getSessionFactory().getStatistics().getEntityFetchCount(), 1 );
|
assertEquals( 1, scope.getSessionFactory().getStatistics().getEntityFetchCount() );
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
s.createQuery("delete Item").executeUpdate();
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "delete Item" ).executeUpdate()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testProjectionCache() throws Exception {
|
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
final String queryString = "select i.description as desc from Item i where i.name='widget'";
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
Item i = new Item();
|
|
||||||
i.setName("widget");
|
|
||||||
i.setDescription("A really top-quality, full-featured widget.");
|
|
||||||
s.save(i);
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
QueryStatistics qs = s.getSessionFactory().getStatistics().getQueryStatistics( queryString );
|
|
||||||
EntityStatistics es = s.getSessionFactory().getStatistics().getEntityStatistics( Item.class.getName() );
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 0 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 1 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 1 );
|
|
||||||
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
List result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
assertEquals( i.getDescription(), ( result.get( 0 ) ) );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 0 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
assertEquals( i.getDescription(), result.get( 0 ) );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 1 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
Map m = (Map) result.get(0);
|
|
||||||
assertEquals( 1, m.size() );
|
|
||||||
assertEquals( i.getDescription(), m.get( "desc" ) );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( "hit count should go up since data is not transformed until after it is cached", qs.getCacheHitCount(), 2 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
m = (Map) result.get(0);
|
|
||||||
assertEquals(1, m.size());
|
|
||||||
assertEquals( i.getDescription(), m.get( "desc" ) );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( "hit count should go up since data is not transformed until after it is cachedr", qs.getCacheHitCount(), 3 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
assertTrue( Hibernate.isInitialized( result.get(0) ) );
|
|
||||||
i = (Item) s.get( Item.class, new Long(i.getId()) );
|
|
||||||
i.setName("widget");
|
|
||||||
i.setDescription("A middle-quality widget.");
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 4 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 2 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 2 );
|
|
||||||
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
t = s.beginTransaction();
|
|
||||||
result = s.createQuery( queryString ).setCacheable(true).list();
|
|
||||||
assertEquals( result.size(), 1 );
|
|
||||||
i = (Item) s.get( Item.class, new Long(i.getId()) );
|
|
||||||
assertEquals( result.get(0), "A middle-quality widget." );
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 4 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 3 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 3 );
|
|
||||||
|
|
||||||
s.delete(i);
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( qs.getCacheHitCount(), 4 );
|
|
||||||
assertEquals( qs.getCacheMissCount(), 3 );
|
|
||||||
assertEquals( qs.getCachePutCount(), 3 );
|
|
||||||
assertEquals( qs.getExecutionCount(), 3 );
|
|
||||||
assertEquals( es.getFetchCount(), 0 ); //check that it was being cached
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-4459" )
|
|
||||||
public void testGetByCompositeId() {
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
s.persist( new EntityWithCompositeKey( PK ) );
|
|
||||||
Query query = s.createQuery( "FROM EntityWithCompositeKey e WHERE e.pk = :pk" );
|
|
||||||
query.setCacheable( true );
|
|
||||||
query.setParameter( "pk", PK );
|
|
||||||
assertEquals(1, query.list().size( ));
|
|
||||||
s.getTransaction().rollback();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
EntityWithStringCompositeKey entity = new EntityWithStringCompositeKey();
|
|
||||||
StringCompositeKey key = new StringCompositeKey();
|
|
||||||
key.setAnalog( "foo1" );
|
|
||||||
key.setDevice( "foo2" );
|
|
||||||
key.setDeviceType( "foo3" );
|
|
||||||
key.setSubstation( "foo4" );
|
|
||||||
entity.setPk( key );
|
|
||||||
s.persist( entity );
|
|
||||||
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<EntityWithStringCompositeKey> criteria = criteriaBuilder.createQuery( EntityWithStringCompositeKey.class );
|
|
||||||
Root<EntityWithStringCompositeKey> root = criteria.from( EntityWithStringCompositeKey.class );
|
|
||||||
criteria.where( criteriaBuilder.equal( root.get( "pk" ), key ) );
|
|
||||||
s.createQuery( criteria ).setCacheable( true );
|
|
||||||
|
|
||||||
assertEquals( 1, s.createQuery( criteria ).list().size() );
|
|
||||||
// Criteria c = s.createCriteria(
|
|
||||||
// EntityWithStringCompositeKey.class ).add( Restrictions.eq(
|
|
||||||
// "pk", key ) );
|
|
||||||
// c.setCacheable( true );
|
|
||||||
// assertEquals( 1, c.list().size() );
|
|
||||||
s.getTransaction().rollback();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-3051" )
|
|
||||||
public void testScalarSQLQuery() {
|
|
||||||
sessionFactory().getCache().evictQueryRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
Item item = new Item();
|
|
||||||
item.setName("fooName");
|
|
||||||
item.setDescription("fooDescription");
|
|
||||||
s.persist(item);
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
|
|
||||||
// Note: StandardQueryCache#put handles single results and multiple results differently. So, test both
|
|
||||||
// 1 and 2+ scalars.
|
|
||||||
|
|
||||||
String sqlQuery = "select name, description from Items";
|
|
||||||
NativeQuery query = s.createNativeQuery( sqlQuery);
|
|
||||||
query.setCacheable(true);
|
|
||||||
query.addScalar("name");
|
|
||||||
query.addScalar("description");
|
|
||||||
Object[] result1 = (Object[]) query.uniqueResult();
|
|
||||||
assertNotNull( result1 );
|
|
||||||
assertEquals( result1.length, 2 );
|
|
||||||
assertEquals( result1[0], "fooName" );
|
|
||||||
assertEquals( result1[1], "fooDescription" );
|
|
||||||
|
|
||||||
sqlQuery = "select name from Items";
|
|
||||||
query = s.createNativeQuery(sqlQuery);
|
|
||||||
query.setCacheable(true);
|
|
||||||
query.addScalar("name");
|
|
||||||
String result2 = (String) query.uniqueResult();
|
|
||||||
assertNotNull( result2 );
|
|
||||||
assertEquals( result2, "fooName" );
|
|
||||||
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Test
|
|
||||||
// public void testGetByCompositeIdNoCache() {
|
|
||||||
// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e.pk = :pk");
|
|
||||||
// query.setParameter("pk", PK);
|
|
||||||
// assertEquals(1, query.getResultList().size());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// public void testGetByEntityIself() {
|
|
||||||
// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e = :ent");
|
|
||||||
// query.setParameter("ent", new EntityWithCompositeKey(PK));
|
|
||||||
// assertEquals(1, query.getResultList().size());
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-9962")
|
|
||||||
/* Test courtesy of Giambattista Bloisi */
|
|
||||||
public void testDelayedLoad() throws InterruptedException, ExecutionException {
|
|
||||||
DelayLoadOperations interceptor = new DelayLoadOperations();
|
|
||||||
final SessionBuilder sessionBuilder = sessionFactory().withOptions().interceptor(interceptor);
|
|
||||||
Item item1 = new Item();
|
|
||||||
item1.setName("Item1");
|
|
||||||
item1.setDescription("Washington");
|
|
||||||
Session s1 = sessionBuilder.openSession();
|
|
||||||
Transaction tx1 = s1.beginTransaction();
|
|
||||||
s1.persist(item1);
|
|
||||||
tx1.commit();
|
|
||||||
s1.close();
|
|
||||||
|
|
||||||
Item item2 = new Item();
|
|
||||||
item2.setName("Item2");
|
|
||||||
item2.setDescription("Chicago");
|
|
||||||
Session s2 = sessionBuilder.openSession();
|
|
||||||
Transaction tx2 = s2.beginTransaction();
|
|
||||||
s2.persist(item2);
|
|
||||||
tx2.commit();
|
|
||||||
s2.close();
|
|
||||||
|
|
||||||
interceptor.blockOnLoad();
|
|
||||||
|
|
||||||
Future<Item> fetchedItem = executor.submit(new Callable<Item>() {
|
|
||||||
public Item call() throws Exception {
|
|
||||||
return findByDescription(sessionBuilder, "Washington");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// wait for the onLoad listener to be called
|
|
||||||
interceptor.waitOnLoad();
|
|
||||||
|
|
||||||
Session s3 = sessionBuilder.openSession();
|
|
||||||
Transaction tx3 = s3.beginTransaction();
|
|
||||||
item1.setDescription("New York");
|
|
||||||
item2.setDescription("Washington");
|
|
||||||
s3.update(item1);
|
|
||||||
s3.update(item2);
|
|
||||||
tx3.commit();
|
|
||||||
s3.close();
|
|
||||||
|
|
||||||
interceptor.unblockOnLoad();
|
|
||||||
|
|
||||||
// the concurrent query was executed before the data was amended so
|
|
||||||
// let's expect "Item1" to be returned as living in Washington
|
|
||||||
Item fetched = fetchedItem.get();
|
|
||||||
assertEquals("Item1", fetched.getName());
|
|
||||||
|
|
||||||
// Query again: now "Item2" is expected to live in Washington
|
|
||||||
fetched = findByDescription(sessionBuilder, "Washington");
|
|
||||||
assertEquals("Item2", fetched.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Item findByDescription(SessionBuilder sessionBuilder, final String description) {
|
|
||||||
Session s = sessionBuilder.openSession();
|
|
||||||
try {
|
|
||||||
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<Item> criteria = criteriaBuilder.createQuery( Item.class );
|
|
||||||
Root<Item> root = criteria.from( Item.class );
|
|
||||||
criteria.where( criteriaBuilder.equal( root.get( "description" ), description ) );
|
|
||||||
|
|
||||||
return s.createQuery( criteria ).setCacheable( true ).setReadOnly( true ).uniqueResult();
|
|
||||||
// return (Item) s.createCriteria(Item.class)
|
|
||||||
// .setCacheable(true)
|
|
||||||
// .setReadOnly(true)
|
|
||||||
// .add(Restrictions.eq("description", description))
|
|
||||||
// .uniqueResult();
|
|
||||||
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DelayLoadOperations extends EmptyInterceptor {
|
|
||||||
|
|
||||||
private volatile CountDownLatch blockLatch;
|
|
||||||
private volatile CountDownLatch waitLatch;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
|
|
||||||
// Synchronize load and update activities
|
|
||||||
try {
|
|
||||||
if (waitLatch != null) {
|
|
||||||
waitLatch.countDown();
|
|
||||||
}
|
|
||||||
if (blockLatch != null) {
|
|
||||||
blockLatch.await();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void blockOnLoad() {
|
|
||||||
blockLatch = new CountDownLatch(1);
|
|
||||||
waitLatch = new CountDownLatch(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitOnLoad() throws InterruptedException {
|
|
||||||
waitLatch.await();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unblockOnLoad() {
|
|
||||||
if (blockLatch != null) {
|
|
||||||
blockLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue