Java 如何在Spring Boot中随父实体一起更新子实体?

Java 如何在Spring Boot中随父实体一起更新子实体?,java,spring-boot,hibernate,spring-data-jpa,hibernate-mapping,Java,Spring Boot,Hibernate,Spring Data Jpa,Hibernate Mapping,我正在尝试使用JPA更新父实体和子实体(随父实体一起提供)。我试了很多方法,但都做不到。它给了我以下的错误 javax.persistence.EntityExistsException:具有 相同的标识符值已与会话联系人关联(6) 以下是实体: 父->User.java Child->Contact.java 在我的Service.java中,我是这样更新的 @Override @Transactional public User update(Long id, User user) {

我正在尝试使用JPA更新父实体和子实体(随父实体一起提供)。我试了很多方法,但都做不到。它给了我以下的错误

javax.persistence.EntityExistsException:具有 相同的标识符值已与会话联系人关联(6)

以下是实体:

父->User.java

Child->Contact.java

在我的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);
}
{
    "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);
}
@覆盖
@交易的
公共用户更新(长id,用户){
可选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);
返回userRepo.save(curUser);
}

因为您在持久性上下文中有两次表示相同的用户(即相同的id)

此行在持久性上下文中加载用户
curUser

可选curUser=userRepo.findById(id);
这一行通过id使
user
成为同一个用户,但这是一个不同的瞬间

user.setId(curUser.get().getId());
最后,这一行尝试将
user
添加到持久性上下文中

userRepo.save(用户);
这将导致两个实例连接到持久性上下文,同时用相同的id表示相同的用户,这将导致不一致的状态,因为JPA不知道要持久化哪个版本。因此,这是禁止的,并抛出您看到的异常

在你的情况下

Optional<User> curUser = userRepo.findById(id);
    
user.setId(curUser.get().getId());
我们应该做到这一点

关于你的评论:

引用对象也存在同样的问题。您必须确保:要么加载实体并更改其属性,要么不直接或间接地通过引用加载实体并保存根据请求构造的分离实体


如果加载一个实体,然后尝试保存该实体的分离实例,则会出现此类错误。

如果用户和联系人都有repository,请先尝试在联系人respository中保存联系人。让我知道这种方法是否有用you@jafarmlp我试过了,但还是犯了同样的错误。非常感谢你的回答和时间。我能修好它。
@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);
}
Optional<User> curUser = userRepo.findById(id);
    
user.setId(curUser.get().getId());
user.setId(id);