如何在SpringBoot中更新子实体和父实体?

5rgfhyps  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(457)

我正在尝试使用jpa更新父实体和子实体(随父实体一起提供)。我试过很多方法,但都做不到。它给了我以下的错误。
javax.persistence.entityexistsexception:具有相同标识符值的不同对象已与会话联系人关联(6)
以下是实体,
父->user.java

@Entity
public class User extends Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_generator")
    @SequenceGenerator(name = "seq_generator", sequenceName = "seq_users", initialValue = 1, allocationSize = 1)
    private Long id;

    private String firstName;
    private String lastName;
    private String email;
    private String password;
    private String street;
    private String city;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "userContact")
    private Contact contact;
}

子->contact.java

@Entity
public class Contact extends Serializable {

    private static final long serialVersionUID = 1L;

    @Getter(value = AccessLevel.NONE)
    @Setter(value = AccessLevel.NONE)
    @Id
    @Column(insertable = false, updatable = false)
    private Long id;

    @MapsId
    @OneToOne
    @JoinColumn(name = "id", nullable = false)
    private User userContact;

    private String phone;
}

在我的service.java中,我是这样更新的,

@Override
@Transactional
public User update(Long id, User user) {
    Optional<User> curUser = userRepo.findById(id);

    user.setId(curUser.get().getId());
    user.setStreet(curUser.get().getStreet());
    user.setCity(curUser.get().getCity());

    Contact contact = user.getContact();
    contact.setUserContact(user);

    user.setContact(contact);

    return userRepo.save(user);
}

更新json负载是这样的,

{
    "firstName": "FirstName",
    "lastName": "LastName",
    "email": "Email",
    "password": "Password",
    "contact": {
        "phone": "0123456789"
    }
}

为什么我不能马上更新?插入工作正常,但此更新不工作。我做错什么了?如果有人能帮我,我真的很感激。提前谢谢。
这是我尝试的新方法,

@Override
@Transactional
public User update(Long id, User user) {
    Optional<User> curUser = userRepo.findById(id);

    curUser.setFirstName(user.getFirstName());
    curUser.setlastName(user.getLastName());
    curUser.setEmail(user.getEmail());
    curUser.setPassword(user.getPassword());

    Contact contact = user.getContact();
    contact.setUserContact(curUser);

    curUser.setContact(contact);

    return userRepo.save(curUser);
}
zlhcx6iw

zlhcx6iw1#

因为在持久性上下文中有两次表示相同的用户(即相同的id)。
此行加载用户 curUser 在持久性上下文中。

Optional<User> curUser = userRepo.findById(id);

这条线使 user 同一个用户的id,但它是一个不同的瞬间。

user.setId(curUser.get().getId());

最后这一行试图添加 user 到持久性上下文。

userRepo.save(user);

这将导致两个示例被附加到持久性上下文,同时用相同的id表示相同的用户,这将导致不一致的状态,因为jpa不知道要持久化哪个版本。因此,这是被禁止的,并抛出你看到的异常。
在你的情况下

Optional<User> curUser = userRepo.findById(id);

user.setId(curUser.get().getId());

user.setId(id);

应该会成功的。
关于您的意见:
引用的对象也存在同样的问题。您必须确保:要么加载实体并更改其属性,要么不加载实体,而不是直接或间接地通过引用加载实体,并保存从您的请求构造的分离实体。
如果加载一个实体,然后尝试保存它的分离示例,则会出现这种错误。

相关问题