MappingException: Unknown entity when using Entity subclass as Command - java

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:
public class UserCommand {
public static UserCommand fromUser(User user) {
UserCommand command = new UserCommand();
// fill UserCommand fields
return command;
}
public void toUser(User user) {
// fill User fields
}
}
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.

Agreed with Hoaz. If you want to copy each field of your object from DTO to DB easily you can use the Dozer utility.

I just ran into this issue myself for Hibernate 3.6 you can explicitly define a subclass.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html
With xml you could:
<subclass name="DomesticCat"
discriminator-value="D">
<property name="name" type="string"/>
</subclass>
or with Annotation:
#Entity #DiscriminatorValue("D")
public class DomesticCat extends Cat {
//class implementation here
}
EDIT:
Don't forget the descriminator.
<discriminitor insert="false" formula="'C'" />
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, insert=false)
#DiscriminatorFormula("'C'")
#DiscriminatorValue("C")
public class Cat { ... }

Related

Returning Entity from Service method is a bad practice?

I've heard when you want to return some object from a service method, you have to define a DTO object (or POJO object generated with JSON Schema) instead of using an Entity.
To make it clear, here is the example:
We have an entity and a jpa repository for it:
#Data
#Entity
#Table(name = "tables")
public class Table {
#Id
private Long id;
private String brand;
}
This is a bad practice:
#Service
public class MyService {
#Autowired
private TableRepository tableRepository;
#Transactional
public Table create() {
Table table = new Table();
// Some logic for creating and saving table
return table;
}
}
This is a good practice:
#Service
public class MyService {
#Autowired
private TableRepository tableRepository;
#Transactional
public TableDTO create() {
Table table = new Table();
// Some logic for creating and saving table
// Logic for converting Table object to TableDTO object
return tableDTO;
}
}
Why is this so?
Thank you!
Probably you mean a DTO (Data Transfer Object), not DAO (Data Access Object). Let me clarify this:
Data Transfer Object:
A Pojo that represents a piece of information. Usually it has aggregated data in it.
Data Access Object:
An object that performs access to some kind of persistence storage for retrieving information, someone considers it a synonim of Repository, someone not.
Entity:
An object that represents data that has been retrieved from the database.
Why is returning an Entity from the Service considered a bad practice?
The reason is that the Entity is something that is very close to the database. It contains primary key, someone could guess your database structure from it and the set of the data in case of query can be verbose. Hence, it is preferable to have some kind of logic, usually a mapper, that hides primary key and aggregates data to be less verbose and to not expose the db structure. Also, while the Entity is built on the table structure, the DTO can be customized in base of caller needs. Usually it contains exactly the data that is needed for some action and nothing more than this. Suppose you have thirdy party software that calls your backend services: you should not expose the db structure (Entities) to this service. It is better to define a contract, with the minimal information needed for this thirdy party service to operate, and expose only this part of the information, hiding all the rest.
Hope that's a little bit more clear now.
Edit:
Of course there are other good reasons for using DTOs instead of Entities, this is only an introductory explanation to the subject.

Is it ok to pass interface of DTO to DAO

It's about passing interface of DTO to DAO.
For example I have following code
public interface User {
String getName();
}
public class SimpleUser implements User {
protected String name;
public SimpleUser(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
// Mapped by Hibernate
public class PersistentUser extends SimpleUser {
private Long id;
// Constructor
// Getters for id and name
// Setters for id and name
}
I'm using generic DAO. Is it ok if I create DAO with using interface User instead PersistentUser?
User user = new PersistentUser(name);
UserDao.create(user);
I read a lot of topics on stack but not figured out is this approach ok or no. Please help me. Maybe this is stupid and I can achive only problems.
About separating beans.
I did this because some classes I want to share via API module, that can be used outside to create entities and pass them to my application. Because they uses interface I developed so I can pass them to my DAO for persisting.
Generally, I would say it is ok, but there are a few hidden problems. A developer could cast the object down or access some state via a toString method that shouldn't be accessible. If you don't be careful, it could happen that state is serialized as JSON/XML in webservices that shouldn't be serialized. The list goes on.
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(PersistentUser.class)
interface User {
String getName();
}
Querying could look like this
List<User> dtos = entityViewManager.applySetting(
EntityViewSetting.create(User.class),
criteriaBuilderFactory.create(em, PersistentUser.class)
).getResultList();

(Spring / Hibernate) Initialize children objects strategy

I have a form that should be bind to a complex object that wrap a lot of children, every time before loading this form I have to initialize all children object in a method that only have a lot of new statements and calling a setter method, I have to repeat this scenario for a lot of forms and other complex objects
Is there a better strategy than the initializeEmployee method?
For example:
#Entity
public class Employee {
Integer Id;
Contract contract;
Name name;
List<Certificate> list;
// getter and setters
}
#Entity
public class Contract {
String telephoneNum;
String email;
Address address;
// getter and setters
}
#Entity
public class Address {
String streetName;
String streetNum;
String city;
}
public class Name {
String fName;
String mName;
String lName;
// getter and setters
}
// And another class for certificates
public initializeEmployee() {
Employee emplyee = new Employee();
Name name = new Name();
employee.setName(name);
Contract contract = new Contract();
Address address = new Address();
contract.setAddress(address);
employee.setContract(contract);
// set all other employee inner objects,
}
EDIT:
According to below answers, it seems that there is no optimal answer. However, I could use the Entity constructor or a Factory Design Pattern.
But both solutions don't solve my other problem in initializing all fields strategy with Required and Optional fields.
For example:
If I have Name as required (i.e. the Employee entity will not persisted if Name object attributes are empty, on the other side the Contract entity is an optional. and I cannot persist an empty Contract object to the database, so I have to make it null first before persistence, then reinitialize it after persistence like the following
// Set Contract to null if its attributes are empty
Contract contract = employee.getContract()
if(contract.getTelephoneNum().isEmpty && contract.getEmail().isEmpty() && contract.getAddress().isEmpty()){
empolyee.setContract(null);
}
employeeDAO.persist(employee);
// reinitialize the object so it could binded if the the user edit the fields.
employee.setContract(new Contract());
You can add constructors (it is their role after all) to your entities to instanciate these fields if having a null value has no meaning for your case.
Another way, if you don't like adding contructors, is to add a static factory method to instanciate your bean which will look like initializeEmployee() but with potential parameters and returning an Employee object. http://en.wikipedia.org/wiki/Factory_method_pattern
Similarly, you can instanciate your collections too, as there is probably no meaning for a null collection (but there is one for an empty collection).
You can add behaviour to your entities, don't be locked in Anemic Domain Model which is considered an anti-pattern by Martin Fowler http://www.martinfowler.com/bliki/AnemicDomainModel.html
EDIT
I see you are using dao.persist(entity): you are probably using JPA. If so, maybe it is best to not modify your object graph (on the front side) and add an EntityListener (in the persistence layer) for Employee: here is a link for Hibernate EntityListener (it is a JPA feature, so if you are using another framework don't worry) http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html
With an EntityListener, you can add small "aop like" actions before persistence and after. This will allow you to not deal with null values on the domain and front layers and will ensure that every entity fits in any case (better validation).
In PrePersist: you'all add your code to check null values (possibly with custom methods "isEmpty()" on the domain classes) and nullify fields if needed. In PostPersist you add your new object.
I couldn't get what you really need, but I think you could try this way:
#Entity
public class Employee {
Integer Id;
Contract contract = new Contract();
Name name = new Name();
List<Certificate> list;
// getter and setters
}
#Entity
public class Contract {
String telephoneNum;
String email;
Address address = new Address();
// getter and setters
}
I'm not sure it reduces the verbosity at all but since this is a UI issue, you could initialize the editable objects in your flow.xml and then put it all together in an Employee instance prior to saving to the DB.
<on-start>
<evaluate expression="new foo.bar.Name()" result="flowScope.employeeName" />
<evaluate expression="new foo.bar.Contract()" result="flowScope.contract" />
<evaluate expression="new foo.bar.Address()" result="flowScope.address" />
</on-start>
Actually I would advise against using Hibernate Entities directly in GUI. In many cases (I assume in yours too, but I'm missing some details on your use-case) it is useful to use a Data Transfer Object pattern instead. You can create such DTO that is GUI specific, has only those fields that you need, and the structure is only as complex as needed.
After specific user action (like save e.g.) use those DTOs (on event handling) to create your Entities that will be persisted.
Unless your case is that just entering the GUI screen causes Entities creation, then I would recommend Factory pattern.
Also note that in many cases initialization of component objects that are making up the main object (Employee in your example) are better to be initialized in constructor of main object, eg. if you expect that Contract cannot be null - initialize it in constructor. The same for the list of Certificates and others.

Exclude field in JPA Entity Listener

I have an entity class in my Enterprise Java application that has an entity listener attached to it:
#Entity
#EntityListeners(ChangeListener.class)
public class MyEntity {
#Id
private long id;
private String name;
private Integer result;
private Boolean dirty;
...
}
However, I would like it so that the entity listener got triggered for all fields except the boolean one. Is there any way exclude a field from triggering the entity listener without making it transient?
I'm using Java EE 5 with Hibernate.
However, it is possible if you implement your own solution. I've had the same need for audit log business requirement, so designed my own AuditField annotation, and applied to the fields to be audit-logged.
Here's the example in one entity bean - Site.
#AuditField(exclude={EntityActionType.DELETE})
#Column(name = "site_code", nullable = false)
private String siteCode;
So, the example indicates the 'siteCode' is a field to audit log, except DELETE action. (EntityActionType is an enum and it contains CRUD operations.)
Also, the EntityListenerhas this part of code.
#PostPersist
public void created(Site pEntity) {
log(pEntity, EntityActionType.CREATE);
}
#PreUpdate
public void updated(Site pEntity) {
log(pEntity, EntityActionType.UPDATE);
}
#PreRemove
public void deleted(Site pEntity) {
log(pEntity, EntityActionType.DELETE);
}
Now what it has to do in log() is, to figure what fields are to audit log and what custom actions are involved optionally.
However, there's another to consider.
If you put the annotation at another entity variable, what fields of the entity have to be logged? (i.e. chained logging)
It's your choice whether what are annotated with #AuditField only in the entity or some other ways. For my case, we decided to log only the entity ID, which is a PK of a DB table. However, I wanted to make it flexible assuming the business can change. So, all the entites must implement auditValue() method, which is coming from a base entity class, and the default implementation (that's overridable) is to return its ID.
There is some kind of mixing of concepts here. EntityListeners are not notified about changes in attribute values - not for single attribute, neither for all attributes.
For reason they are called lifecycle callbacks. They are triggered by following lifecycle events of entity:
persist (pre/post)
load (post)
update(pre/post)
remove (pre/post)
For each one of them there is matching annotation. So answer is that it is not possible to limit this functionality by type of persistent attributes.

Controlling result list from org.hibernate.Query.list when using joined subclass

I have a User class, which is mapped to the "USERS" table in database with Hibernate. There is also a class ApplicationUser, which extends the User class and is mapped as a joined subclass in Hibernate to database table "APPLICATIONUSERS". Like this:
public class User implements Serializable {
//properties, getters, setters omitted for readability
}
public class ApplicationUser extends User implements Serializable {
//properties, getters, setters omitted for readability
}
<hibernate-mapping package="com.initech.domain">
<class name="com.initech.domain.User" table="USERS">
<!-- properties omitted for readability -->
<joined-subclass name="com.initech.domain.ApplicationUser" table="APPLICATIONUSERS">
<!-- properties omitted for readability -->
</joined-subclass>
</class>
</hibernate-mapping>
The problem I have is that when I get a list of users (some of them may be "normal" users and some application users), everything works fine - I get a List object, where each item is either a User or ApplicationUser object. The method (simplified a bit, may contain typos):
public List findUsersByLoginName(String argLoginName){
StringBuilder sb = new StringBuilder("from User user where lower(user.loginName) = :argLoginName");
Query myQuery = this.sessionFactory.getCurrentSession().createQuery(sb.toString());
myQuery.setString("argLoginName", argLoginName.toLowerCase());
List userList = myQuery.list();
return userList;
}
However, if there is only one user found, who is an ApplicationUser, the list contains two objects: one User object and one ApplicationUser object, representing the same user. This is a problem e.g. when the calling method is expecting each list item to be a different, unique User object.
Is there some alternative to checking for this case manually, e.g. using some other method of returning a list, where each object represents a different user also when the list size is one?

Categories

Resources