views:

1142

answers:

2

Hello good people. I 'm trying to build a user and a contact management project. i have a lot of classes so will limit it to what are in concern here. i have a userAccount, userProfile, and group here is the UserAccount Mapping

@Id @GeneratedValue
@Column(name="USER_ACCOUNT_ID")
private Long ID; 
 ......
 @Column(name="EMAIL", length=100, unique=true)
private String email;

@OneToOne(targetEntity=UserProfileImpl.class,cascade={CascadeType.ALL})
 @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@JoinColumn(name="USER_PROFILE_ID")
private UserProfile profile;

 @OneToMany(targetEntity=GroupImpl.class, cascade={CascadeType.ALL})
 //    @JoinColumn(name="USER_ACCOUNT_ID")
@JoinTable(name = "USER_ACCOUNT_CONTACT_GROUP", joinColumns = @JoinColumn(name = "USER_ACCOUNT_ID"), inverseJoinColumns = @JoinColumn(name = "GROUP_ID"))
@org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Group> groups = new HashSet<Group>();
........

here is the userProfile

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="USER_PROFILE_ID")
private Long ID;
.....
 @OneToOne(mappedBy="profile", targetEntity=UserAccountImpl.class)
private UserAccount userAccount;
.....

here is the group

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="GROUP_ID")
private Long ID;    
.......
@Column(name="NAME", length=100, unique=true)
private String Name;

@ManyToOne(targetEntity=UserAccountImpl.class)
@JoinColumn(name="USER_ACCOUNT_ID",nullable=false)
private UserAccount userAccount;

so basically this is it.Everything went fine before a did a bidirectional association adding userAccount object to group.so on testing. i create userProfile, userAccount ,and group(using spring @autowired) .
On the setUP (@Before) method i set few prop to userProfile and add it to useAccount along with its prop and persist it and then set the useAccount to the group.
on the tearDown(@After) i delete the userACcount .
on my testSave (saves the group) works fine (using the same session for all the operations) but there is no delete sql query on the console for the group but it deletes the userAccount Though.
By deleting the userAccount in the teardown method i was hoping group should be deleted to.But that that's not the case.
worse because of the unique constraint on name of the group the other tests are failling.I search on the net but everything i try doesn't seem to work.Who can save me :) ? i mean how am i supposed to do it? thanks for reading

this is an update on what i've tried based on response i've got. i've added this to group.setUserAccount(null) to my removeGroup which is now this

public void removeGroup(Group group) {
    try{
       if(this.groups.contains(group)){
        group.setUserAccount(null);
        this.groups.remove(group);
       }
    } catch(Exception ex){
        ex.printStackTrace();
    }
}

so for the test i used which has the same behavior ie deletes the userAccount but not the group

ua1.removeGroup(g1);
uaDao.delete(ua1);

i guess it's not entering the if block because i should have the same behavior as this one:

 g1.setUserAccount(null);
 uaDao.delete(ua1);

this other one throws an error

PropertyValueException: not-null property references a null or transient value

so i think i'll delete the group using :

gDao.delete(g1);
uaDao.delete(ua1);

hoping that i might find a way to go about it.Thanks to people who have helped me out especially Pascal if you had another idea or found something wrong about my code i'll be more than glad to correct it.thanks for reading

+1  A: 

Using @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) is fine but...

Are you also setting the userAccount reference in the Group to null?

You still have to manage the Java relationships manually i.e. you have to set the parent to null in the child if the relationship is bidirectional.

Pascal Thivent
I'm not sure if i get you could you elaborate? thanks.so before i save the child , i save the parent , set the parent in the child like so `group.setUserAccount(userAccount)` and then save the child.So if i got you right to make my scenario happen ie deletion of the parent cascades to the child (deletes the child), i'll have to set `group.setUserAccount(null);` is that what you saying? thanks for reading and thanks for answering
black sensei
Yes this is what I'm saying.
Pascal Thivent
thanks Pascal.you are helping me out once again. thanks, basically all my knowledge on hibernate is from stackoverflow.
black sensei
i've updated my post.seems something is not working well
black sensei
+2  A: 

First off if the UserAccount -> Group relationship is bi-directional then you would need to map the inverse collection side as

@OneToMany(targetEntity=GroupImpl.class, cascade{CascadeType.ALL},mappedBy="userAccount")

So now Hibernate knows that the UserAccount is the owner of the collection. Now for deleting as @Pascal says you need to unbind both sides. Since Hibernate ignores the collection, the owner is responsible for binding the relationship so basically a helper method like this creates the association in UserAccount

public void addGroup(Group group){
     group.setUserAccount(this);
     groups.add(group);
}

now for deleting another helper method

public void removeGroup(Group group){
    group.setUserAccount(null);
    groups.remove(group);
}

now for removal

UserAccount ua = //load user account object
for(Group g : ua.getGroups())
      ua.removeGroup(g);

session.delete(ua);

Your code should work now. You don't have to do it my way but I hope you get the drift.DELETE_ORPHAN should take care of your cascade deletion of groups

non sequitor
thanks bruv i got the drift.i didn't know about the helper method i did have removeGroup but didn't set userAccount to null ad didn't know it has to be call before the deletion of the userAccount.Thanks a lot
black sensei
i updated my post.it's not affecting the result.it's the same thing
black sensei
Did you include `mappedBy=userAccount` in the `@OneToMany`?
non sequitor
yes. i think it's due to the fact the UserAccount cannot be null`@JoinColumn(name="USER_ACCOUNT_ID",nullable=false)` . that's what i think but not sure because a group can't exit without it's owner so i'm a little confused now. thanks for you responsiveness
black sensei
found what i was doing wrong thanks
black sensei