使用Hibernate将子类保持为超类

时间:2010-06-17 09:44:09

标签: hibernate inheritance

我有一个子类和一个超类。但是,只需要保留超类的字段。

session.saveOrUpdate((Superclass) subclass);

如果我执行上述操作,我将收到以下异常。

org.hibernate.MappingException: Unknown entity: test.Superclass
    at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:628)
    at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1366)
    at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:203)
    at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:535)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:103)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:342)
    at $Proxy54.saveOrUpdate(Unknown Source)

如何将子类作为超类保留?我不喜欢创建超类实例,然后从子类实例传递值。因为,如果将来将额外字段添加到超类,很容易忘记更新逻辑。

3 个答案:

答案 0 :(得分:2)

这个问题有一种解决方案,它实际上在StackOverFlow上有所涉及:

Hibernate/NHibernate : how to persist subclass as instance of superclass

Hibernate Documentation

基本上你只是告诉Hibernate使用超类的字符串将你的类保存为超类,如:

session.save( “my.superclass”,子类);

这可能不适用于所有用例,但对我来说只是票证。

答案 1 :(得分:1)

你试图实现的目标会给你带来很多问题。试想一下,如果再次加载数据会发生什么。 Hibernate应该使用哪个类?超类?或者其中一个子类?哪一个?

我建议直接映射超类,然后使用delegate pattern来实现扩展功能(基本上将你的超类转换为传递给“worker”实例的数据对象)。

答案 2 :(得分:0)

我也有兴趣找到一种方法来做到这一点。这是一个激励人心的案例。假设我有一个User对象来代表我的应用程序中的用户。 User对象有一些属性,如用户名,密码,电子邮件地址,名字等,我将存储在数据库中。

当我构建允许用户编辑自己的个人资料的屏幕时,我想要一个“更改密码”的复选框,以便我可以显示/隐藏密码框,我还想要一个“确认密码“这样他们就不会错误地输入它。我不想将这些属性存储在数据库中,并且它们实际上不是User对象的一部分,因此我不希望这些字段存在于User中。但是,许多Web框架使基于正在编辑的对象构建表单页面变得更加容易。

我想解决的方法是创建User的子类,让我们称之为EditableUser,它有一些额外的字段,如“changePassword”和“confirmPassword”,并在我的表单上使用此对象。但问题是Hibernate不知道如何保存EditableUser对象。 (这也是如何从您从数据库加载的用户创建EditableUser的问题,但如果您有一个复制构造函数,这是可行的)

我最终解决这个问题的方法是使用委托:创建一个EditableUser对象,其中包含一个User,以及我不想保存的额外属性。这样做效果相当不错,除了它意味着我在表单上的所有数据绑定都必须更改以访问内部User对象,因此感觉有点混乱。