HHH-12107 - ClassCastException when using L2Cache with "structured_cache"=true
This commit is contained in:
parent
63e4702629
commit
992fdbcf3c
|
@ -28,7 +28,7 @@ import org.hibernate.type.TypeHelper;
|
|||
*/
|
||||
public class StandardCacheEntryImpl implements CacheEntry {
|
||||
private final Serializable[] disassembledState;
|
||||
private final String disassembledStateText;
|
||||
private String disassembledStateText;
|
||||
private final Object version;
|
||||
private final String subclass;
|
||||
|
||||
|
@ -66,8 +66,8 @@ public class StandardCacheEntryImpl implements CacheEntry {
|
|||
this.version = version;
|
||||
}
|
||||
|
||||
StandardCacheEntryImpl(Serializable[] state, String disassembledStateText, String subclass, Object version) {
|
||||
this.disassembledState = state;
|
||||
StandardCacheEntryImpl(Serializable[] disassembledState, String disassembledStateText, String subclass, Object version) {
|
||||
this.disassembledState = disassembledState;
|
||||
this.disassembledStateText = disassembledStateText;
|
||||
this.subclass = subclass;
|
||||
this.version = version;
|
||||
|
@ -138,18 +138,26 @@ public class StandardCacheEntryImpl implements CacheEntry {
|
|||
}
|
||||
|
||||
//assembled state gets put in a new array (we read from cache by value!)
|
||||
final Object[] assembledProps = TypeHelper.assemble(
|
||||
final Object[] state = TypeHelper.assemble(
|
||||
disassembledState,
|
||||
persister.getPropertyTypes(),
|
||||
session, instance
|
||||
);
|
||||
|
||||
if ( disassembledStateText == null ) {
|
||||
disassembledStateText = TypeHelper.toLoggableString(
|
||||
state,
|
||||
persister.getPropertyTypes(),
|
||||
session.getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
//persister.setIdentifier(instance, id); //before calling interceptor, for consistency with normal load
|
||||
|
||||
//TODO: reuse the PreLoadEvent
|
||||
final PreLoadEvent preLoadEvent = new PreLoadEvent( session )
|
||||
.setEntity( instance )
|
||||
.setState( assembledProps )
|
||||
.setState( state )
|
||||
.setId( id )
|
||||
.setPersister( persister );
|
||||
|
||||
|
@ -162,9 +170,9 @@ public class StandardCacheEntryImpl implements CacheEntry {
|
|||
listener.onPreLoad( preLoadEvent );
|
||||
}
|
||||
|
||||
persister.setPropertyValues( instance, assembledProps );
|
||||
persister.setPropertyValues( instance, state );
|
||||
|
||||
return assembledProps;
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,11 +9,9 @@ package org.hibernate.cache.spi.entry;
|
|||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.TypeHelper;
|
||||
|
||||
/**
|
||||
* Structured CacheEntry format for entities. Used to store the entry into the second-level cache
|
||||
|
@ -45,15 +43,15 @@ public class StructuredCacheEntry implements CacheEntryStructure {
|
|||
final Object version = map.get( VERSION_KEY );
|
||||
final EntityPersister subclassPersister = factory.getEntityPersister( subclass );
|
||||
final String[] names = subclassPersister.getPropertyNames();
|
||||
final Serializable[] state = new Serializable[names.length];
|
||||
final Serializable[] disassembledState = new Serializable[names.length];
|
||||
for ( int i = 0; i < names.length; i++ ) {
|
||||
state[i] = (Serializable) map.get( names[i] );
|
||||
disassembledState[i] = (Serializable) map.get( names[i] );
|
||||
}
|
||||
return new StandardCacheEntryImpl(
|
||||
state,
|
||||
TypeHelper.toLoggableString( state, subclassPersister.getPropertyTypes(), factory ),
|
||||
subclass,
|
||||
version
|
||||
disassembledState,
|
||||
null,
|
||||
subclass,
|
||||
version
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalceca
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-12107" )
|
||||
public class StructuredQueryCacheTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
OneToManyWithEmbeddedId.class,
|
||||
OneToManyWithEmbeddedIdChild.class,
|
||||
OneToManyWithEmbeddedIdKey.class
|
||||
};
|
||||
}
|
||||
|
||||
@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
|
||||
@TestForIssue( jiraKey = "HHH-12107" )
|
||||
public void testEmbeddedIdInOneToMany() {
|
||||
|
||||
OneToManyWithEmbeddedIdKey key = new OneToManyWithEmbeddedIdKey( 1234 );
|
||||
final OneToManyWithEmbeddedId o = new OneToManyWithEmbeddedId( key );
|
||||
o.setItems( new HashSet<>() );
|
||||
o.getItems().add( new OneToManyWithEmbeddedIdChild( 1 ) );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.persist( o );
|
||||
});
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
||||
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
||||
assertNotNull( _entity );
|
||||
});
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
OneToManyWithEmbeddedId _entity = session.find( OneToManyWithEmbeddedId.class, key );
|
||||
assertTrue( session.getSessionFactory().getCache().containsEntity( OneToManyWithEmbeddedId.class, key ) );
|
||||
assertNotNull( _entity );
|
||||
});
|
||||
}
|
||||
|
||||
@Entity(name = "OneToManyWithEmbeddedId")
|
||||
public static class OneToManyWithEmbeddedId {
|
||||
|
||||
private OneToManyWithEmbeddedIdKey id;
|
||||
|
||||
private Set<OneToManyWithEmbeddedIdChild> items = new HashSet<>( );
|
||||
|
||||
public OneToManyWithEmbeddedId() {
|
||||
}
|
||||
|
||||
public OneToManyWithEmbeddedId(OneToManyWithEmbeddedIdKey id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@EmbeddedId
|
||||
public OneToManyWithEmbeddedIdKey getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(OneToManyWithEmbeddedIdKey id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, targetEntity = OneToManyWithEmbeddedIdChild.class, orphanRemoval = true)
|
||||
@JoinColumn(name = "parent_id")
|
||||
public Set<OneToManyWithEmbeddedIdChild> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(Set<OneToManyWithEmbeddedIdChild> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "OneToManyWithEmbeddedIdChild")
|
||||
public static class OneToManyWithEmbeddedIdChild {
|
||||
private Integer id;
|
||||
|
||||
public OneToManyWithEmbeddedIdChild() {
|
||||
}
|
||||
|
||||
public OneToManyWithEmbeddedIdChild(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class OneToManyWithEmbeddedIdKey implements Serializable {
|
||||
private Integer id;
|
||||
|
||||
public OneToManyWithEmbeddedIdKey() {
|
||||
}
|
||||
|
||||
public OneToManyWithEmbeddedIdKey(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Column(name = "id")
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue