spring-boot - CascadeType.MERGE 实际上做了什么?
问题描述
我得到了UserDetails
实体表单数据库并将其作为模型属性(MVC)传递。后来,我尝试更新UserDetails
数据库中的更新实体。现在我收到了这个错误。
我的疑问是
- 的用例是什么
CascadeType.MERGE
- Hibernate 如何处理实体
- 如何更新与另一个实体关联的现有实体。
同一实体 [com.rajath.instagram.entity.UserDetails#1] 的多个表示正在合并。托管:[com.rajath.instagram.entity.UserDetails@637bce04];分离:[com.rajath.instagram.entity.UserDetails@2b6247fa];嵌套异常是 java.lang.IllegalStateException:正在合并同一实体 [com.rajath.instagram.entity.UserDetails#1] 的多个表示。托管:[com.rajath.instagram.entity.UserDetails@637bce04];已分离:[com.rajath.instagram.entity.UserDetails@2b6247fa]],根本原因是 java.lang.IllegalStateException:正在合并同一实体 [com.rajath.instagram.entity.UserDetails#1] 的多个表示。托管:[com.rajath.instagram.entity.UserDetails@637bce04];分离:[com.rajath.instagram.entity.UserDetails@2b6247fa]
控制器层:
@PostMapping("/addUserDetails")
public String adduserDetails(@ModelAttribute("user") UserDetails userDetails) {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
regisrationService.updateUserDetails(user.getUsername(), userDetails);
return "redirect:/register/addProfilePhoto";
}
服务层:
@Override
@Transactional
public void updateUserDetails(String username, UserDetails userDetails) {
Optional<InstagramUser> opt = instagramUserJpaDao.findById(username);
InstagramUser user = opt.get();
userDetails.setUser(user);
userDetailsJpaDao.saveAndFlush(userDetails);
}
道层:
@Override
public void updateUserDetails(String username, UserDetails userDetails) {
Session session = manager.unwrap(Session.class);
InstagramUser user = session.get(InstagramUser.class, username);
userDetails.setUser(user);
user.setUserDetails(userDetails);
session.saveOrUpdate(userDetails);
}
我的实体是:
- Instagram用户
// From user details table
@OneToOne(mappedBy="user", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private UserDetails userDetails;
- 用户详情
// From user table, @OneToOne matching because, only one user details entry for a user
@OneToOne(fetch=FetchType.EAGER,
cascade= {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name="username")
private InstagramUser user;
解决方案
您的代码的问题可能InstagramUser.userDetails
不是真的很懒惰,因此当前UserDetails
也被加载到上下文中,因此出现错误。尝试添加(请参阅我回答的最后一段,了解为什么这不是正确的解决方案)optional = false
到映射以查看问题是否消失。
或者,您可以尝试通过以下方式重新排序代码:
UserDetails merged = userDetailsJpaDao.save(userDetails); // I am assuming userDetails.user is null at this point
instagramUserJpaDao.findById(username)
.ifPresent(instagramUser -> merged.setUser(instagramUser));
另请注意,由于在您的原始代码InstagramUser.user
中是关联的反面,因此该行user.setUserDetails(userDetails);
实际上没有做任何事情。您需要填充UserDetails.user
以在两个实体之间建立关联。
推荐阅读
- swift - 如何更改 CVPixelBuffer 数据格式
- c# - 发布传递空模型值以及如何正确删除或修复它?
- javascript - 由于 angulat6 中的撇号符号而无法显示图像
- java - 如何将android库项目转换为fat jar
- node.js - 使用另一台主机中的副本集连接到 mongodb 集群时出错
- google-maps - 使用电子表格中的 API 密钥进行身份验证
- r - 在 R 中运行样本大小不等的两样本 t.test
- android - Kotlin 不理解 ViewModelProviders.of(activity ?: fragment)
- c# - 无法转换类型 func
布尔 - python - Scrapy无法通过xpath找到数据