I have a User object mapped with hibernate annotations working just fine.
Eg
@Entity
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
etc ..
}
I then have a “Add User” form using Spring 3 MVC and I required a command object to back this form, so I subclassed User from above in UserCommand. The UserCommand has some extra stuff on it related to the web interface etc that doesn’t need to be saved as part of a User entity.
Eg
public class UserCommand extends User {
private String initialAddress;
etc
}
So my view/presentation layer basically creates a UserCommand object, fills out the user details and then the controller submits this down to the service/dao layer to persist. Since UserCommand extends (“is-a”) User the dao accepts the UserCommand instance and it passes the dao validation checks (eg ensure has username and password filled out).
However when hibernate actually comes to persist the object as an entity in the db, it seems to realise the actual object is a UserCommand, which isn’t a mapped entity, even though it’s super type is.
The resulting error is;
org.hibernate.MappingException: Unknown entity: com.example.UserCommand
org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:691)
org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1494)
org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:202)
org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:531)
org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
Is there a way around this issue? I seemed like an obvious thing to do, the form is filling out a User so just use an extension of User (ie UserCommand) as the form’s backing command object.
Or am I going to have to break the inheritance, duplicate User’s fields in UserCommand and the explicitly copy all the values from UserCommand into User during the form submit?
I think mixing database and view entities is a bad practice. These are different layers and they should operate on different DTOs. Usually I use following pattern to convert between two layers:
If conversion between view and database DTOs require some complex logic you can move these methods to conversion service.
One benefit from splitting these entities is validation. You can specify JSR-303 annotations to validate these beans and in most cases they will be different for UI and DB.