Hibernate是否有可能执行以下实体结构?
@Entity
public class Person {
@OneToMany
private Map<Class<? extends PersonRole>, PersonRole> personRoles;
public <T extends PersonRole> T getRole(Class<T> roleClass) {
return roleClass.cast(roles.get(roleClass));
}
}
@Entity
public abstract class PersonRole {
@ManyToOne
private Person person;
}
基本上Hibernate可以持久保存这个映射的实体,但是不能再从数据库加载它,但有以下异常:
Exception in thread "main" org.hibernate.HibernateException: null index column for collection: de.his.cs.sys.hibernate.Person.roles
at org.hibernate.persister.collection.AbstractCollectionPersister.readIndex(AbstractCollectionPersister.java:822)
at org.hibernate.collection.internal.PersistentMap.readFrom(PersistentMap.java:277)
at org.hibernate.loader.Loader.readCollectionElement(Loader.java:1189)
at org.hibernate.loader.Loader.readCollectionElements(Loader.java:804)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:655)
at org.hibernate.loader.Loader.doQuery(Loader.java:854)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:293)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:263)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2094)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:61)
解决方法可能是使用“简单”集合并使用拦截器填充地图,但我希望有可能在没有额外基础设施的情况下实现此目的。
答案 0 :(得分:1)
可以实现一个Hibernate UserType
,它将类映射到字符串并返回
@OneToMany
@MapKey(name = "className" type=@Type(type="namespace.classToNameUserType"))
private Map<Class<? extends PersonRole>, PersonRole> personRoles;
答案 1 :(得分:0)
问题基本上在我看来,hibernate需要依赖map键的持久属性。因此,该解决方案将新属性添加到抽象类 RersonRole :
private Class<?> className = this.getClass();
然后可以在类Person:
中的@MapKey注释中引用它@OneToMany
@MapKey(name = "className")
private Map<Class<? extends PersonRole>, PersonRole> personRoles;
通过这种映射,hibernate现在可以在没有其他基础设施的情况下填充Map。
从我的观点来看,大多数优雅的解决方案都有添加持久属性的缺点,这只是因为hibernate而需要(如果我找到了问题的根本原因)。