Joined: Sat Aug 12, 2006 1:20 am Posts: 7
|
I have one-to-many set based bi-directional association. See relavant code below. The cascade setting is all, delete-orphan. Now if a child is removed from collection of one entity but added to the collection of another entity, I wouldn't expect it to be deleted. ( Essentially the cascade induced delete gets offset by another cascade induced update ). However, the entity removed from the collection gets deleted in spite of being referenced from the collection of another entity. I've attached some excerpt from the debug logs. If you notice, the pretty printer logs indicate that SampleGroup#3 is being referenced by SampleGroup#1, but in spite of this SampleGroup#3 is being deleted.
Am i missing something or is this a bug ? If this is indeed a bug, does anyone know of a workaround ?
Thanks,
Radhakrishnan
3.2.2
Code: @Entity public class SampleGroup implements TreeNode { @Id @GeneratedValue private Long id; @ManyToOne(optional=true) private SampleGroup myParent; @OneToMany(mappedBy="myParent") @Cascade({CascadeType.ALL,CascadeType.DELETE_ORPHAN}) private Set<SampleGroup> includesGroups = new LinkedHashSet<SampleGroup>();
@Embedded private TreeNodeInfo treeNodeInfo = new TreeNodeInfo(); private String treeName; private String groupName; public SampleGroup() { super(); treeName = " Simple Group "; }
public TreeNodeInfo getNodeInfo() { return treeNodeInfo; }
public TreeNode getParent() { return myParent; }
public String getTreeName() { return treeName; }
/** * @return the myParent */ public SampleGroup getMyParent() { return myParent; }
/** * @param myParent the myParent to set */ public void setMyParent(SampleGroup myParent) { this.myParent = myParent; }
/** * @return the treeNodeInfo */ public TreeNodeInfo getTreeNodeInfo() { return treeNodeInfo; }
/** * @param treeNodeInfo the treeNodeInfo to set */ public void setTreeNodeInfo(TreeNodeInfo treeNodeInfo) { this.treeNodeInfo = treeNodeInfo; }
/** * @return the groupName */ public String getGroupName() { return groupName; }
/** * @param groupName the groupName to set */ public void setGroupName(String groupName) { this.groupName = groupName; }
/** * @param treeName the treeName to set */ public void setTreeName(String treeName) { this.treeName = treeName; }
/** * @return the id */ public Long getId() { return id; } public void includeGroup(SampleGroup group) { group.setMyParent(this); includesGroups.add(group); } public void excludeGroup(SampleGroup group) { if (this.equals(group.getMyParent())) { group.setMyParent(null); includesGroups.remove(group); } } public boolean includesGroup(SampleGroup group) { return includesGroups.contains(group); } private static MessageFormat messageFormat = new MessageFormat("tree=''{0}'', group=''{1}'', id={2}, {3} "); @Override public String toString() { return messageFormat.format(new Object[]{treeName,groupName,id,treeNodeInfo}); }
Code: SampleGroup group1 = new SampleGroup(); group1.setGroupName("group 1"); SampleGroup group2 = new SampleGroup(); group2.setGroupName("group 2"); SampleGroup group3 = new SampleGroup(); group3.setGroupName("group 3"); group1.includeGroup(group2); group2.includeGroup(group3); sampleGroupRepository.save(group1); assertNotNull(group1.getId()); assertNotNull(group2.getId()); assertNotNull(group3.getId()); //Flushes the session and clears it. flushAndClear();
SampleGroup _1_reloaded = sampleGroupRepository.findById( group1.getId() ); SampleGroup _2_reloaded = sampleGroupRepository.findById( group2.getId() ); SampleGroup _3_reloaded = sampleGroupRepository.findById( group3.getId() ); assertNotNull( _1_reloaded ); assertNotNull( _2_reloaded ); assertNotNull( _3_reloaded ); assertTrue( _1_reloaded.includesGroup(_2_reloaded) ); assertTrue( _2_reloaded.includesGroup(_3_reloaded) ); //Move 3 from 2 to 1. _2_reloaded.excludeGroup(_3_reloaded); _1_reloaded.includeGroup(_3_reloaded); assertTrue( _1_reloaded.includesGroup(_2_reloaded) ); assertTrue( _1_reloaded.includesGroup(_3_reloaded) ); assertFalse( _2_reloaded.includesGroup(_3_reloaded) );
sampleGroupRepository.update(_1_reloaded); flushAndClear(); _1_reloaded = sampleGroupRepository.findById( group1.getId() ); _2_reloaded = sampleGroupRepository.findById( group2.getId() ); _3_reloaded = sampleGroupRepository.findById( group3.getId() );
assertNotNull(_3_reloaded);//This fails. //assertNotNull(_2_reloaded); //This also fails.
HyperSonic 1.8.0.4
Hibernate: insert into sample_group (id, my_parent, tree_node_info_lft, tree_node_info_rgt, tree_name, group_name) values (null, ?, ?, ?, ?, ?) Hibernate: call identity() Hibernate: insert into sample_group (id, my_parent, tree_node_info_lft, tree_node_info_rgt, tree_name, group_name) values (null, ?, ?, ?, ?, ?) Hibernate: call identity() Hibernate: insert into sample_group (id, my_parent, tree_node_info_lft, tree_node_info_rgt, tree_name, group_name) values (null, ?, ?, ?, ?, ?) Hibernate: call identity() Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=? Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=? Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=? Hibernate: select includesgr0_.my_parent as my6_1_, includesgr0_.id as id1_, includesgr0_.id as id95_0_, includesgr0_.my_parent as my6_95_0_, includesgr0_.tree_node_info_lft as tree2_95_0_, includesgr0_.tree_node_info_rgt as tree3_95_0_, includesgr0_.tree_name as tree4_95_0_, includesgr0_.group_name as group5_95_0_ from sample_group includesgr0_ where includesgr0_.my_parent in (?, ?, ?) Hibernate: delete from sample_group where id=? Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=? Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=? Hibernate: select samplegrou0_.id as id95_1_, samplegrou0_.my_parent as my6_95_1_, samplegrou0_.tree_node_info_lft as tree2_95_1_, samplegrou0_.tree_node_info_rgt as tree3_95_1_, samplegrou0_.tree_name as tree4_95_1_, samplegrou0_.group_name as group5_95_1_, samplegrou1_.id as id95_0_, samplegrou1_.my_parent as my6_95_0_, samplegrou1_.tree_node_info_lft as tree2_95_0_, samplegrou1_.tree_node_info_rgt as tree3_95_0_, samplegrou1_.tree_name as tree4_95_0_, samplegrou1_.group_name as group5_95_0_ from sample_group samplegrou0_ left outer join sample_group samplegrou1_ on samplegrou0_.my_parent=samplegrou1_.id where samplegrou0_.id=?
DEBUG org.hibernate.event.def.AbstractFlushingEventListener : Scheduling collection removes/(re)creates/updates DEBUG org.hibernate.event.def.AbstractFlushingEventListener : Flushed: 0 insertions, 0 updates, 1 deletions to 3 objects DEBUG org.hibernate.event.def.AbstractFlushingEventListener : Flushed: 0 (re)creations, 2 updates, 1 removals to 3 collections DEBUG org.hibernate.pretty.Printer : listing entities: DEBUG org.hibernate.pretty.Printer : tavant.twms.infra.SampleGroup{treeNodeInfo=component[lft,rgt]{lft=1, rgt=2}, treeName= Simple Group , groupName=group 1, includesGroups=[tavant.twms.infra.SampleGroup#2, tavant.twms.infra.SampleGroup#3], myParent=null, id=1} DEBUG org.hibernate.pretty.Printer : tavant.twms.infra.SampleGroup{treeNodeInfo=component[lft,rgt]{lft=1, rgt=2}, treeName= Simple Group , groupName=group 2, includesGroups=[], myParent=tavant.twms.infra.SampleGroup#1, id=2} DEBUG org.hibernate.pretty.Printer : tavant.twms.infra.SampleGroup{treeNodeInfo=component[lft,rgt]{lft=1, rgt=2}, treeName= Simple Group , groupName=group 3, includesGroups=[], myParent=tavant.twms.infra.SampleGroup#1, id=3} DEBUG org.hibernate.event.def.AbstractFlushingEventListener : executing flush DEBUG org.hibernate.jdbc.ConnectionManager : registering flush begin DEBUG org.hibernate.persister.entity.AbstractEntityPersister : Deleting entity: [tavant.twms.infra.SampleGroup#3]
|
|