Java 具有相同标识符的不同对象已与会话关联
尝试更新“照片”时出现错误:Java 具有相同标识符的不同对象已与会话关联,java,spring,hibernate,Java,Spring,Hibernate,尝试更新“照片”时出现错误: Photo photo = photoRepository.findById(id); List<Photo> photos = user.getPhotos(); user.setPhotos(photos.add(photo)); userRepository.update(user); 看起来,不同的对象具有相同的标识符(第一行:photo,第二行:photo,inside user.getPhotos()) 因此,我
Photo photo = photoRepository.findById(id);
List<Photo> photos = user.getPhotos();
user.setPhotos(photos.add(photo));
userRepository.update(user);
看起来,不同的对象具有相同的标识符(第一行:photo,第二行:photo,inside user.getPhotos())
因此,我无法更新我的用户。
如何避免这个错误
用户存储库:
tx = session.beginTransaction();
user = (User) session.get(User.class, id);
session.getTransaction().commit();
您的代码是有缺陷的,在ORM世界中管理双向关系时,您永远不应该允许对内部状态进行外部修改。目前,您有一个服务方法,它从用户中提取照片列表并添加一个新的。这样,您只需设置关系的一面。您还应该在
Photo
对象上调用setUser
Photo photo = photoRepository.findById(id);
List<Photo> photos = user.getPhotos();
photo.setUser(user);
user.setPhotos(photos.add(photo));
userRepository.update(user);
假设您的照片
与用户
在同一个包中,设置用户
可以是可见的包(即设置用户
方法上没有公共
或受保护
)
现在,在您的代码中,您可以简单地执行以下操作
Photo photo = photoRepository.findById(id);
user.addPhoto(photo);
userRepository.update(user);
无需使其更复杂,添加照片的逻辑现在已经很好地封装和测试了 您正在使用Spring,为什么要手动管理事务?您永远不应该像那样获取集合并向其中添加对象。您正在泄漏内部状态。你应该在你的
User
上有一个addPhoto
方法,该方法将Photo
添加到集合中,并且假设它是双向关系,该方法也会执行Photo.setUser
操作。对不起,我改为User.setPhotos(photos.add(Photo));我已经有photo.setUser()。手动管理交易是什么意思?你有其他的方法吗?哪一种更糟。。。您应该允许在外部设置内部集合,这对于托管集合尤其危险。您应该阅读注释。。。
public class User {
public Set<Photo> getPhotos() {
// Unmodifiable to protect internal state.
return Collections.unmodifiableSet(this.photos);
}
// No setPhotos!
public void addPhoto(Photo photo) {
photo.setUser(this);
this.photos.add(photo);
}
}
Photo photo = photoRepository.findById(id);
user.addPhoto(photo);
userRepository.update(user);