Hibernate saves a new object with every merge
Question
I am having a peculiar problem. Every time,I call merge, on the session, Hibernate persists a brand new object. I am using Hibernate 3.6 in a Spring MVC application.
Please find below my code:
My hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect </property>
<!-- this will show us all sql statements -->
<property name="hibernate.show_sql"> true </property>
<property name="connection.pool_size">1</property>
<!-- <property name="hbm2ddl.auto">create</property>-->
<!-- mapping files -->
<mapping resource="com/hibernate/hbm/employee.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
My employee.hbm.xml
<hibernate-mapping default-lazy="true">
<class name="com.spring.model.Employee" table="employee">
<id name="empId" type="long" column="empId" unsaved-value="null">
<generator class="sequence">
<param name="sequence">hibernate_sequence</param>
</generator>
</id>
<version name="version" column="version" unsaved-value="null"
type="long" />
<component name="identity" class="com.spring.model.Identity">
<property name="firstname" column="firstname" not-null="true" />
<property name="lastname" column="lastname" not-null="true" />
<property name="email" column="emailid" not-null="true" />
</component>
<!-- <property name="birthday" column="birthday"/> -->
<property name="fileDataBytes" column="filedata" />
<property name="fileName" column="fileName" />
<property name="fileContentType" column="fileContentType" />
</class>
</hibernate-mapping>
My model classes
public class Employee extends BaseModel{
private CommonsMultipartFile fileData;
private byte[] fileDataBytes;
private String fileName;
private String fileContentType;
private Identity identity;
private long empId;
//getters,setters /equals() on empId field
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (empId ^ (empId >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (empId != other.empId)
return false;
return true;
}
public class BaseModel implements Serializable{
private Long version;
//gettes,setters
public class Identity {
protected String firstname;
protected String lastname;
protected String email;
//getters.setters
My employeeDAOImpl.java's save method
public long saveEmployee(Employee employee) throws Exception {
public Employee getEmployeeById(long empId) {
// TODO Auto-generated method stub
return (Employee) getSessionFactory().getCurrentSession().load(Employee.class,empId);
}
}
// TODO Auto-generated method stub
if(employee.getEmpId() == 0){
return (Long)getSessionFactory().getCurrentSession().save(employee);
}else{
Employee empInSession = getEmployeeById(employee.getEmpId());
getSessionFactory().getCurrentSession().merge(employee);
return employee.getEmpId();
}
}
Note : i already had loaded the object in the GET cycle , but to ensure that the object is loaded in the cache, I am still loading it before the call to merge().Ideally, the merge shouldn't be required at all,as the object becomes persistent. Why the hell does this happen? Hibernate saves a new object with the changed properties and saves it. Shouldn't it check via the empId field which is in the equals check??
Solution 2
Well, this seemed to be a Spring issue. Got resolved by adding @SessionAttributes to my Controller class.Seems innocuous but actually was the root of the problem. Marten on the Spring forum helps me here
OTHER TIPS
Try adding an equals and hashcode to your employee class.