Thank you very much for the "MyPersistenceLayer" solution.
I now use this in combination with dozer to map a delta class with some changes to the retrieved class. So that I can update only a few attributes.
See the following code example (A user has a job and a salary..)
Job.java
Code:
package com.test;
public class Job {
private Integer id;
private String name;
// setters and getters are present but not written here in example
}
Salary.javaCode:
package com.test;
public class Salary {
private Integer id;
private Integer money;
// setters and getters are present but not written here in example
}
and the
User.javaCode:
package com.test;
public class User {
private Integer id;
private String name;
private Job job;
private Salary salary;
// setters and getters are present but not written here in example
}
The mapping from hibernate looks like:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.test.User" table="users">
<id name="id" column="id">
<generator class="increment"/>
</id>
<property name="name" column="name"/>
<many-to-one name="job" class="com.test.Job" column="job_id"/>
<many-to-one name="salary" class="com.test.Salary" column="sal_id"/>
</class>
<class name="com.test.Job" table="jobs">
<id name="id" column="id">
<generator class="increment"/>
</id>
<property name="name" column="name"/>
</class>
<class name="com.test.Salary" table="salaries">
<id name="id" column="id">
<generator class="increment"/>
</id>
<property name="money" column="money"/>
</class>
</hibernate-mapping>
And the dozer mapping looks as follows:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"
"http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">
<mappings>
<mapping map-null="false">
<class-a>com.test.Job</class-a>
<class-b>com.test.Job</class-b>
</mapping>
<mapping map-null="false">
<class-a>com.test.Salary</class-a>
<class-b>com.test.Salary</class-b>
</mapping>
<mapping map-null="false">
<class-a>com.test.User</class-a>
<class-b>com.test.User</class-b>
<field copy-by-reference="true">
<a>job</a>
<b>job</b>
</field>
<field copy-by-reference="true">
<a>salary</a>
<b>salary</b>
</field>
</mapping>
</mappings>
In my main code I can now do the following:
Code:
private void addUser() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
// Set a new Job to the user, first create a delta-user
// this deltaUser has a new name, new job and new salary,
// but we are talking about the same user
final User deltaUser = new User();
deltaUser.setName("'delta name'");
final Job searchedJob3 = (Job) session.load(Job.class, Integer.valueOf(3));
deltaUser.setJob(searchedJob3);
final Salary searchedSal3 = (Salary) session.load(Salary.class, Integer.valueOf(3));
deltaUser.setSalary(searchedSal3);
// lookup the real-user
final User user = (User) session.load(User.class, Integer.valueOf(1));
// deproxy the user, else dozer won't work correct
final User deproxyUser = MyPersistenceLayer.deproxy(user, User.class);
// use dozer to map the delta user to deproxy user (do not map null values, see dozer configuration.)
mapper.map(deltaUser, deproxyUser);
session.flush();
session.getTransaction().commit();
}
The combination from Hibernate + dozer allows me to workaround the "do not update null-values in database" issue.
This works very good if you have multiple attributes in the classes, in this way no programming is needed but everything can be done using configuration.