HHH-12657 - Fix ClassCastException for cached natural-id entity with subclasses

This commit is contained in:
Guenther Demetz 2018-06-01 10:22:54 +02:00 committed by Chris Cranford
parent 292a4e4337
commit 7a4b38c6b7
4 changed files with 264 additions and 212 deletions

View File

@ -307,7 +307,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
);
}
if ( persistentClass.hasNaturalId() && persistentClass.getNaturalIdCacheRegionName() != null ) {
if ( persistentClass.hasNaturalId() && persistentClass instanceof RootClass && persistentClass.getNaturalIdCacheRegionName() != null ) {
locateCacheRegionConfigBuilder( persistentClass.getNaturalIdCacheRegionName() ).addNaturalIdConfig(
(RootClass) persistentClass,
accessType

View File

@ -1,210 +1,210 @@
/*
* 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.naturalid.mutable.cached;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.stat.NaturalIdCacheStatistics;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.cache.CachingRegionFactory;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class CachedMutableNaturalIdStrictReadWriteTest extends
CachedMutableNaturalIdTest {
@Override
public void configure(Configuration cfg) {
super.configure(cfg);
cfg.setProperty( CachingRegionFactory.DEFAULT_ACCESSTYPE, "read-write" );
}
@Test
@TestForIssue( jiraKey = "HHH-9203" )
public void testToMapConversion() {
sessionFactory().getStatistics().clear();
final Session session = openSession();
session.getTransaction().begin();
final AllCached it = new AllCached( "IT" );
session.save( it );
session.getTransaction().commit();
session.close();
final NaturalIdCacheStatistics stats = sessionFactory().getStatistics().getNaturalIdCacheStatistics(
"hibernate.test." + AllCached.class.getName() + "##NaturalId"
);
assertEquals( 1, stats.getPutCount() );
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testInsertedNaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.flush();
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
assertEquals(1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testInsertedNaturalIdNotCachedAfterTransactionFailure() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.flush();
session.getTransaction().rollback();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNull(it);
assertEquals(0, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testChangedNaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
it.setName("modified");
session.flush();
session.getTransaction().commit();
session.close();
session.getSessionFactory().getStatistics().clear();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("modified");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
session.close();
assertEquals(1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testChangedNaturalIdNotCachedAfterTransactionFailure() {
Session session = openSession();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
it.setName("modified");
session.flush();
session.getTransaction().rollback();
session.close();
session.getSessionFactory().getStatistics().clear();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("modified");
assertNull(it);
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
session.delete(it);
session.getTransaction().commit();
session.close();
assertEquals(0, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7309" )
public void testInsertUpdateEntity_NaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it ); // schedules an InsertAction
it.setSurname("1234"); // schedules an UpdateAction, without bug-fix
// this will re-cache natural-id with identical key and at same time invalidate it
session.flush();
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
assertEquals("In a strict access strategy we would excpect a hit here", 1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-9200" )
public void testNaturalIdCacheStatisticsReset() {
final String naturalIdCacheRegion = "hibernate.test.org.hibernate.test.naturalid.mutable.cached.Another##NaturalId";
sessionFactory().getStatistics().clear();
Session session = openSession();
session.beginTransaction();
final Another it = new Another( "IT");
session.save( it );
session.getTransaction().commit();
session.close();
NaturalIdCacheStatistics statistics = sessionFactory().getStatistics().getNaturalIdCacheStatistics( naturalIdCacheRegion );
assertEquals( 1, statistics.getPutCount() );
sessionFactory().getStatistics().clear();
// Refresh statistics reference.
statistics = sessionFactory().getStatistics().getNaturalIdCacheStatistics( naturalIdCacheRegion );
assertEquals( 0, statistics.getPutCount() );
session = openSession();
session.beginTransaction();
session.delete( it );
session.getTransaction().commit();
session.clear();
}
}
/*
* 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.naturalid.mutable.cached;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.stat.NaturalIdCacheStatistics;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.cache.CachingRegionFactory;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class CachedMutableNaturalIdStrictReadWriteTest extends
CachedMutableNaturalIdTest {
@Override
public void configure(Configuration cfg) {
super.configure(cfg);
cfg.setProperty( CachingRegionFactory.DEFAULT_ACCESSTYPE, "read-write" );
}
@Test
@TestForIssue( jiraKey = "HHH-9203" )
public void testToMapConversion() {
sessionFactory().getStatistics().clear();
final Session session = openSession();
session.getTransaction().begin();
final AllCached it = new AllCached( "IT" );
session.save( it );
session.getTransaction().commit();
session.close();
final NaturalIdCacheStatistics stats = sessionFactory().getStatistics().getNaturalIdCacheStatistics(
"hibernate.test." + AllCached.class.getName() + "##NaturalId"
);
assertEquals( 1, stats.getPutCount() );
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testInsertedNaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.flush();
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
assertEquals(1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testInsertedNaturalIdNotCachedAfterTransactionFailure() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.flush();
session.getTransaction().rollback();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNull(it);
assertEquals(0, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testChangedNaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
it.setName("modified");
session.flush();
session.getTransaction().commit();
session.close();
session.getSessionFactory().getStatistics().clear();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("modified");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
session.close();
assertEquals(1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7278" )
public void testChangedNaturalIdNotCachedAfterTransactionFailure() {
Session session = openSession();
session.beginTransaction();
Another it = new Another( "it");
session.save( it );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
it.setName("modified");
session.flush();
session.getTransaction().rollback();
session.close();
session.getSessionFactory().getStatistics().clear();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("modified");
assertNull(it);
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
session.delete(it);
session.getTransaction().commit();
session.close();
assertEquals(0, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-7309" )
public void testInsertUpdateEntity_NaturalIdCachedAfterTransactionSuccess() {
Session session = openSession();
session.getSessionFactory().getStatistics().clear();
session.beginTransaction();
Another it = new Another( "it");
session.save( it ); // schedules an InsertAction
it.setSurname("1234"); // schedules an UpdateAction, without bug-fix
// this will re-cache natural-id with identical key and at same time invalidate it
session.flush();
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
it = (Another) session.bySimpleNaturalId(Another.class).load("it");
assertNotNull(it);
session.delete(it);
session.getTransaction().commit();
assertEquals("In a strict access strategy we would excpect a hit here", 1, session.getSessionFactory().getStatistics().getNaturalIdCacheHitCount());
}
@Test
@TestForIssue( jiraKey = "HHH-9200" )
public void testNaturalIdCacheStatisticsReset() {
final String naturalIdCacheRegion = "hibernate.test.org.hibernate.test.naturalid.mutable.cached.Another##NaturalId";
sessionFactory().getStatistics().clear();
Session session = openSession();
session.beginTransaction();
final Another it = new Another( "IT");
session.save( it );
session.getTransaction().commit();
session.close();
NaturalIdCacheStatistics statistics = sessionFactory().getStatistics().getNaturalIdCacheStatistics( naturalIdCacheRegion );
assertEquals( 1, statistics.getPutCount() );
sessionFactory().getStatistics().clear();
// Refresh statistics reference.
statistics = sessionFactory().getStatistics().getNaturalIdCacheStatistics( naturalIdCacheRegion );
assertEquals( 0, statistics.getPutCount() );
session = openSession();
session.beginTransaction();
session.delete( it );
session.getTransaction().commit();
session.clear();
}
}

View File

@ -29,7 +29,7 @@ import org.junit.Test;
public abstract class CachedMutableNaturalIdTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {A.class, Another.class, AllCached.class, B.class};
return new Class[] {A.class, Another.class, AllCached.class, B.class, SubClass.class};
}
@Override
@ -166,6 +166,33 @@ public abstract class CachedMutableNaturalIdTest extends BaseCoreFunctionalTestC
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-12657" )
public void testbySimpleNaturalIdResolveEntityFrom2LCacheSubClass() {
Session session = openSession();
session.beginTransaction();
SubClass it = new SubClass( "it" );
session.save( it );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
// verify instance can be retrieved by bySimpleNaturalId called on superclass
it = (SubClass) session.bySimpleNaturalId( AllCached.class ).load( "it" );
assertNotNull( it );
// verify instance can be retrieved by bySimpleNaturalId called on concrete sub class too
it = session.bySimpleNaturalId( SubClass.class ).load( "it" );
assertNotNull( it );
session.delete( it );
session.getTransaction().commit();
session.close();
}
@Test
public void testReattachementUnmodifiedInstance() {
Session session = openSession();

View File

@ -0,0 +1,25 @@
/*
* 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.naturalid.mutable.cached;
import javax.persistence.Entity;
/**
* @author Guenther Demetz
*/
@Entity
public class SubClass extends AllCached {
public SubClass() {
super();
}
public SubClass(String name) {
super(name);
}
}