1

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)

一种解决方法可能是使用“简单”集合并用拦截器填充地图,但我希望有可能在没有额外基础设施的情况下实现这一点。

4

2 回答 2

1

有可能实现一个 Hibernate UserType,它将类映射到一个字符串并返回

@OneToMany
@MapKey(name = "className" type=@Type(type="namespace.classToNameUserType"))
private Map<Class<? extends PersonRole>, PersonRole> personRoles;

有关示例 UserType,请参见此处

于 2012-10-23T11:37:06.627 回答
0

在我看来,这个问题基本上是,休眠需要依赖于映射键的持久属性。因此,该解决方案向抽象类RersonRole添加了一个新属性:

private Class<?> className = this.getClass();

那么就可以在Person类的@MapKey注解中引用它:

@OneToMany
@MapKey(name = "className")
private Map<Class<? extends PersonRole>, PersonRole> personRoles;

有了这个映射,hibernate 现在可以在没有进一步基础设施的情况下填充 Map。

从我的角度来看,大多数优雅的解决方案都有添加持久属性的缺点,这只是因为休眠需要(如果我得到问题的根本原因正确)。

于 2012-10-24T07:48:38.473 回答