JPA 2 - OneToOne交叉引用

时间:2011-03-25 14:02:35

标签: java jpa persistence eclipselink one-to-one

我一直在努力解决这个问题,似乎无法在任何地方找到解决方案。也许我误解了一些事情,但如果有人能为我清理一些东西,我会非常感激。

我正在尝试在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 用户实例在Controller中创建,然后通过服务层发送到持久保存对象的DAO类。

我首先创建并保留新的用户对象。

然后我创建一个新的 FacebookProfile 并将新创建的用户放入其中(setUser)。然后我坚持使用FacebookProfile对象。

用户ID现在存储在FacebookProfile数据库表中,但是没有用户对FacebookProfile的引用,因此以下代码返回 NullPointerException

User tempUser = userService.findUserById(newUser.getId());
System.out.println("ID "+tempUser.getFbprofile().getId());

以下是控制器中的代码,如果不清楚的话:

        //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 引用是在用户对象中设置的,但从未保留,因为它是在用户对象被持久化了。我使用 JPA2 EclipseLink

如果某人有解决方案,我们将不胜感激。

1 个答案:

答案 0 :(得分:2)

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);
       }
    }