2010-06-17 48 views
3

我有一个子类和一个超类。但是,只有超类的字段需要保留。使用Hibernate作为超类继承子类

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) 

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

+0

'Superclass'是否被映射?例外情况表明它不是。 – 2010-06-17 09:46:45

+0

Ooops,应该是“org.hibernate.MappingException:未知实体:test.Subclass”。 – franziga 2010-06-17 09:59:49

回答

1

你试图达到什么会导致你很多问题。试想一下,如果你再次加载数据会发生什么。 Hibernate应该使用哪个类?超类?还是其中一个子类?哪一个?

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

+0

我只会将数据加载到超类。 如果超类添加了额外的字段,您的建议还需要通知更新委托。 – franziga 2010-06-17 09:59:10

0

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

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

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

我最终解决此问题的方式是使用委派:创建一个EditableUser对象,其中包含一个User,以及我不想保存的额外属性。这合理地工作得很好,除了它意味着我的表单上的所有数据绑定都必须更改为访问内部User对象,所以感觉有点混乱。