I have a subclass and a superclass. However, only the fields of the superclass are needed to be persist.
session.saveOrUpdate((Superclass) subclass);
If I do the above, I will get the following exception.
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.ref开发者_JAVA百科lect.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)
How can I persist a subclass as a superclass? I do not prefer creating a superclass instance and then passing the values from the subclass instance. Because, it is easy to forget updating the logic if extra fields are added to superclass in the future.
There is a type of solution to this problem, and it's actually covered here on StackOverFlow:
Hibernate/NHibernate : how to persist subclass as instance of superclass
Hibernate Documentation
Essentially you just tell Hibernate to save your class as the superclass using a string for the superclass like:
session.save("my.superclass",subclass);
This might not work in all use cases, but for me it was just the ticket.
What you try to achieve will cause you a lot of problems. Just imagine what happens if you load the data again. Which class is Hibernate supposed to use? The superclass? Or one of the subclasses? Which one?
I suggest to map the superclass directly and then use the delegate pattern to implement the extended functionality (basically turning your superclass in a data object which gets passed to "worker" instances).
I am also interested in finding out a way to do this. Here is a motivating case. Let's say I have a User object to represent a user in my application. The User object has a handful of properties, like username, password, email address, first name, etc that I will store in a database.
When I am building the screen that lets a user edit their own profile, I want to have a check box for "Change Password", so that I can show / hide the password box, and I also want a "confirm password" field so they don't mis-type it. I don't want to store these properties in the database, and they aren't really part of the User object, so I don't want those fields to exist in the User. However, a lot of web frameworks make it much easier to build a form page based on an object that is being edited.
The way I would like to solve this is to make a subclass of User, let's call it EditableUser, which has a few extra fields like "changePassword" and "confirmPassword", and use this object on my form. But the problem is that Hibernate will not know how to save an EditableUser object. (It's also a problem of how to create an EditableUser from a User that you load from the database, but this is doable if you have a copy constructor)
The way I have ended up working around this problem is to use delegation: create an EditableUser object that has a User inside of it, along with the extra properties that I don't want to save. This works reasonably well, except that it means that all of my data binding on the form has to change to access the inner User object, so it feels kind of messy.
精彩评论