JPA 2 - OneToOne cross reference
I have been struggling with this issue for a while now, and can't seem to find a solution anywhere. Maybe I have misunderstood something, but would really appreciate it if someone could clear up things for me.
I am trying to create a OneToOne bidirectional relationsship between a User.class and a FacebookProfile.class. That is I want to be able to look up the corresponding User entity from the FacebookProfile entity, and vice versa:
userInstance.getFbprofile();
fbprofileInstance.getUser();
My User.class:
@Entity @Access(value=AccessType.FIELD) public class User implements UserDetails { @OneToOne(mappedBy="user") private FacebookProfile fbprofile; }
My FacebookProfile.class:
@Entity @Access(value=AccessType.FIELD) public class FacebookProfile { @OneToOne (cascade=CascadeType.ALL) @JoinColumn(name="USER") private User user; }
The new FacebookProfile and User instances are created in a Controller, and then sent through a Service layer to a DAO class which persists the objects.
I first create and persist a new User object.
I then create a new FacebookProfile and puts the newly created User in it (setUser). I then persist the FacebookProfile object.
The User ID is now stored in the FacebookProfile database table, but there is no reference from the User to the FacebookProfile so the following code returns a NullPointerException:
User tempUser = userService.findUserById(newUser.getId()); System.out.println("ID "+tempUser.getFbprofile().getId());
Below is the code from the Controller if something is unclear:
//Check if the Facebook user already exist FacebookProfile fbprofile = facebookProfileService.findFacebookProfileById(fbId); User newUser; //Create a new FacebookProfile if it doesn't exist if(fbprofile == null){ //Check if there is a user registered with the facebook email newUser = userService.findUserByEmail(fbEmail); // No User and No FacebookProfile exists if(!newUser.isEnabled()){ newUser = new User(); newUser.setFirstname(fbFirstname); newUser.setLastname(fbLastname); //Set email Email mail = new Email(); mail.setAddress(fbEmail); mail.setName("Facebook"); newUser.addEmail(mail); //Set gender if(fbGender.equalsIgnoreCase("female")){ newUser.setGender(Gender.FEMALE); }else if(fbGender.equalsIgnoreCase("male")) { newUser.setGender(Gender.MALE); } userService.createUser(newUser); } FacebookProfile newProfile = new FacebookProfile(); newProfile.setId(Long.parseLong(fbId)); newProfile.setUsername(fbUsername); newProfile.setFirstname(fbFirstname); newProfile.setLastname(fbLastname); newProfile.setName(fbName); newProfile.setEmail(fbEmail); if(!fbHometown.equals("")){ newProfile.setHometown(fbHometown); newProfile.setHometownID(Long.parseLong(fbHometownID)); } if(!fbLocation.equals("")){ newProfile.setLocation(fbLocation); newProfile.setLocationID(Long.parseLong(fbLocationID)); } newProfile.setLink(fbLink); if(fbGender.equalsIgnoreCase("male")){ newProfile.setGender(Gender.MALE); }else if (fbGender.equalsIgnoreCase("female")) { newProfile.setGender(Gender.FEMALE); } newProfile.setUser(newUser); this.facebookProfileService.c开发者_开发百科reateNewFacebookProfile(newProfile); //newUser.setFbprofile(newProfile); }else { //There already exists a FacebookProfile newUser = fbprofile.getUser(); }
I feel like I have tried every possible solution to this and haven't got it to work. I suspect that in one of my earlier attempts that the fbprofile reference was set in the User object, but never persisted because it was set after the User object was persisted. I am using JPA2 and EclipseLink.
If someone's got a solution to this it would be much appreciated.
Bi-Directional relations is not maintained by JPA. JPA designers had thought that maintaining bi-directional relations can cause deadlocks, inconsistencies... Toplink was supporting bi-directional relations before JPA.. I have used Toplink for many years, I did come accross some inconsistencies related to bi-directional relations.. You should maintain bi-directional relations manually.. Such as ;
newProfile.setUser(newUser);
newUser.setFbProfile(newProfile);
EDIT :
Well, you want me to elaborate my answer.. You should change your code that persist FbProfile entity such as ;
newProfile.setUser(newUser);
newUser.setFbprofile(newProfile);
this.facebookProfileService.createNewFacebookProfile(newProfile);
As an alternative , you could also change FbProfile setUser method ;
public void setUser(User aUser) {
if (this.user==aUser)
return;
if (this.user != null) {
this.user.setFbProfile(null);
}
this.user = aUser;
if (this.user!=null) {
this.user.setFbprofile(this);
}
}
精彩评论