Simple app works wrong with following entity structure
@Entity(name="some_table")
@Inheritance(strategy= InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn( name="TYPE", discriminatorType=DiscriminatorType.STRING )
abstract class EntityBase {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column
private int id;
}
@Entity
@DiscriminatorValue("EntityA")
@Cacheable
class EntityA extends EntityBase {
@Column
private int aColumn;
...
}
@Entity
@DiscriminatorValue("EntityB")
@Cacheable
class EntityB extends EntityBase {
@Column
private int bColumn;
...
}
@Entity(name="holder_table")
@Cacheable
class HolderEntity {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column
private int id;
@ManyToOne(fetch=FetchType.LAZY)
EntityBase holdedEntity;
...
}
For first load or without cache everything works well
After loading of HolderEntity instance from cache, holdedEntity field initialised by object with type EntityBase (abstract class).
Pseudocode:
def a = HolderEntity.get(1)
assert a.holdedEntity.class!=EntityBase //ok
a = HolderEntity.get(1) // load from cache
assert a.holdedEntity.class!=EntityBase //fails (actually EntityBase_$$_jvstbbe_0)
During loading from cache hibernate construct entity using special logic:
for field it detect class type by variable type (it's EntityBase class) instead of discriminator (final Type[] types = subclassPersister.getPropertyTypes(); in DefaultLoadEventListener) and call method
SessionImpl.internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) witch "instantiate" abstract class and init fields by data from hibernate cache
It works same for lazy & eager loading of holdedEntity Class type stored in AbstractEntityPersister.EntityMetamodel. It looks like, field type for cache is static, but it's should depend on instance of field
How to solve it without disabling of hibernate L2 cache?
Hibernate 4.3.8 (4.3.6 & 4.3.11 tested also)
Update: test class
That's because Hibernate uses proxies for lazy associations. If you want to disable proxies, you need to add the @Proxy annotation to your entity class mappings:
@Proxy(lazy=false)
If you run this GitHub test, you' see that @Proxy(lazy=false)
solves your problem.