我已经被这个问题困扰了一段时间,似乎无法在任何地方找到解决方案。也许我误解了一些东西,但如果有人能为我澄清事情,我将非常感激。
我正在尝试在 User.class 和 FacebookProfile.class 之间创建 OneToOne 双向关系。 也就是说,我希望能够从 FacebookProfile 实体查找相应的 User 实体,反之亦然:
userInstance.getFbprofile();
fbprofileInstance.getUser();
我的User.class:
@Entity @Access(value=AccessType.FIELD) public class User implements UserDetails { @OneToOne(mappedBy="user") private FacebookProfile fbprofile; }
我的FacebookProfile.class:
@Entity @Access(value=AccessType.FIELD) public class FacebookProfile { @OneToOne (cascade=CascadeType.ALL) @JoinColumn(name="USER") private User user; }
新的 FacebookProfile 和 User 实例在 Controller 中创建,然后通过服务层发送到保存对象的 DAO 类。
我首先创建并保留一个新的User对象。
然后,我创建一个新的 FacebookProfile 并将新创建的 User 放入其中 (setUser)。然后我保留 FacebookProfile 对象。
用户 ID 现在存储在 FacebookProfile 数据库表中,但用户没有对 FacebookProfile 的引用,因此以下代码返回 NullPointerException:
User tempUser = userService.findUserById(newUser.getId()); System.out.println("ID "+tempUser.getFbprofile().getId());
如果有不清楚的地方,下面是 Controller 的代码:
//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.createNewFacebookProfile(newProfile); //newUser.setFbprofile(newProfile); }else { //There already exists a FacebookProfile newUser = fbprofile.getUser(); }
我觉得我已经尝试了所有可能的解决方案,但还没有成功。 我怀疑在我之前的一次尝试中,fbprofile引用是在User对象中设置的,但从未持久化,因为它是在User之后设置的> 对象被持久化。我正在使用 JPA2 和 EclipseLink。
如果有人能解决这个问题,我们将不胜感激。
最佳答案
JPA 不维护双向关系。 JPA 设计者曾认为维护双向关系会导致死锁、不一致... Toplink 在 JPA 之前就支持双向关系.. 我使用 Toplink 已经很多年了,我确实遇到过一些与双向关系相关的不一致问题。 .你应该手动维护双向关系..如;
newProfile.setUser(newUser);
newUser.setFbProfile(newProfile);
编辑:
好吧,您希望我详细说明我的答案。您应该更改保留 FbProfile 实体的代码,例如;
newProfile.setUser(newUser);
newUser.setFbprofile(newProfile);
this.facebookProfileService.createNewFacebookProfile(newProfile);
作为替代方案,您还可以更改 FbProfile setUser 方法;
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);
}
}
关于java - JPA 2 - 一对一交叉引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5433485/