I am using Hibernate 5.6 and have user Profile with Groups, which have Columns, which have ColumnProperties. I'd like to clone a column of a profile and attach it to the column group.
Profile -> Groups -> Columns -> ColumnProperties
I get this error:
10:58:39,793 ERROR [com.myApp.core.rmgt.profile.service.RmgtProfileServiceImpl] (default task-2) javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.myApp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl#124320]
Here's my mapping files:
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtProfileBVOImpl" table="rmgt_t_profile" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtProfileBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_profile_rowguid_seq</param>
</generator>
</id>
...
<set name="groups" table="rmgt_t_group" lazy="false" cascade="all-delete-orphan" order-by="rmgtg_group_order asc">
<key column="rmgtg_fk_profile_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtGroupBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtGroupBVOImpl" table="rmgt_t_group" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtGroupBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_group_rowguid_seq</param>
</generator>
</id>
...
<set name="columns" table="rmgt_t_column" lazy="false" cascade="all-delete-orphan" order-by="rmgtc_column_order asc">
<key column="rmgtc_fk_group_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtColumnBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtColumnBVOImpl" table="rmgt_t_column" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtColumnBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_column_rowguid_seq</param>
</generator>
</id>
...
<set name="columnProperties" table="rmgt_t_column_property" lazy="false" cascade="all-delete-orphan" order-by="rmgtcp_order asc">
<key column="rmgtcp_fk_column_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl" table="rmgt_t_column_property" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtColumnPropertyBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_column_property_rowguid_seq</param>
</generator>
</id>
<property name="key" type="java.lang.String" column="rmgtcp_key" not-null="true" />
<property name="value" type="java.lang.String" column="rmgtcp_value" not-null="true" />
<property name="order" type="java.lang.Integer" column="rmgtcp_order" not-null="true" />
</class>
</hibernate-mapping>
What I do is i fetch a Profile from DB, then I use Spring's BeanUtils.copyProperties()
to create a copy of the column that I want to clone. I made sure to evict all columnProperties before I proceed.
RmgtColumnBVO column = columnService.findLazyById(columnId);
// Evict all properties to force hibernate write new instances to DB
column.getColumnProperties().stream().forEach(x -> profileDAO.getSession().evict(x));
RmgtColumnBVO columnClone = new RmgtColumnBVOImpl();
BeanUtils.copyProperties(column, columnClone);
columnClone.setRowguid(null);
columnClone.setProfileId(profileId);
columnClone.setGroupId(groupId);
Then I null all rowguids of columnProperties objects of the columnClone:
// clone properties
Set<RmgtColumnPropertyBVO> propertys = column.getColumnProperties();
Set<RmgtColumnPropertyBVO> propertysClone = new HashSet<RmgtColumnPropertyBVO>();
for (RmgtColumnPropertyBVO property : propertys) {
RmgtColumnPropertyBVO propertyClone = new RmgtColumnPropertyBVOImpl();
BeanUtils.copyProperties(property, propertyClone);
propertyClone.setRowguid(null);
propertysClone.add(propertyClone);
}
columnClone.setColumnProperties(propertysClone);
After that, I fetch the profile and attach the cloned column to it and save the profile again:
RmgtProfileBVO profile = profileService.findById(column.getProfileId());
profile.getGroup(groupId).getColumns().add(columnClone);
profileService.saveOrUpdate(profile, object.getCreationUser());
What can I do to fix the problem? I don't understand why Hibernate is still complaining about the properties when I evicted every original one.