spring - 子表在 JPA 中的 OneToMany 关系中没有映射
问题描述
我正在尝试在User和Role之间建立一对多的关系。
一个用户可以有多个角色。
这是用户类的代码
@Entity
public class User {
@Id
private int id;
private String name;
private String password;
private String email;
private String phoneNo;
@OneToMany(
targetEntity = Role.class,
mappedBy = "user",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY
)
private Set<Role> roles;
// Getters, setters and Constructor
角色类的代码
@Entity
public class Role {
@Id
@GeneratedValue
private int roleId;
private String role;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// Getters, setters and Constructor
POST request on Postman is
{
"id":101,
"name": "rahul",
"password": "456",
"email": "rahul@gmail.com",
"phoneNo": "1234561234",
"role": [{
"role":"USER"
}]
}
Code on Configuration part
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http)throws Exception
{
http.csrf().disable();
}
@Bean
public BCryptPasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
}
Code On Controller part
@RestController
public class AdminController {
@Autowired
UserRepository userRepo;
@Autowired
BCryptPasswordEncoder encryptPassword;
@PostMapping("/admin/add")
public String addUserByAdmin(@RequestBody User user)
{
String pass = user.getPassword();
String encrypt = encryptPassword.encode(pass);
user.setPassword(encrypt);
userRepo.save(user);
return "User added Successfully";
}
}
角色表通过Jpa连接数据库
public interface RoleRepository extends JpaRepository<Role, Integer> {
}
用户表通过Jpa连接到数据库
public interface UserRepository extends JpaRepository<User,Integer>{
}
这里的问题是用户表被正确映射但角色表没有被映射。
roleId role user_id
NULL NULL NULL
我哪里错了?任何人都可以帮助我吗?
解决方案
在下面的控制器方法中,您是否尝试过调试传入的请求用户对象?
无论如何,我在这里有以下几点:
首先,查看您的请求正文,您的角色字段被命名role
,而您的 User 对象有一个字段roles
,因此,我很确定它null
在您的处理过程中,因为由于字段名称不匹配,它不会在那里被反序列化。尝试将您的请求正文更改为以下内容:
{
"id":101,
"name": "rahul",
"password": "456",
"email": "rahul@gmail.com",
"phoneNo": "1234561234",
"roles": [{
"role":"USER"
}]
}
其次,如果您检查数据库,角色将被持久化,但您的外键user_id
为空。这是意料之中的。您对User对象执行的级联仅意味着(因为您使用CascadeType.ALL)一旦您保存User对象,保存操作也将级联到Role对象但是,JPA 仍然需要知道关系,因此您必须为每个角色对象设置用户。因此,您可以将控制器方法更新为以下内容:
@PostMapping("/admin/add")
public String addUserByAdmin(@RequestBody User user)
{
String pass = user.getPassword();
String encrypt = encryptPassword.encode(pass);
user.setPassword(encrypt);
// JPA needs to know this relationship...
user.getRoles().forEach(role -> role.setUser(user));
userRepo.save(user);
return "User added Successfully";
}
现在您可以尝试查看您的预期行为现在应该发生。
其他建议:
为什么我们在用户请求中传递 ID 字段?您可以将其从您的请求正文中删除,并在下面使用来自动生成您的 ID,以避免在您的所有实体上出现唯一索引或主键违规异常:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
您还可以删除targetEntity = Role.class
映射上的 ,因为它仅用于泛型,并且对于您的情况,显然您没有将泛型用于 Set。更新您的用户对象以进行角色映射:
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Role> roles;
最后,如果您可以将传入的有效负载包装到 DTO 会更好,因为您不想将实体/模型暴露给 API,但我认为这仅适用于您的测试环境。
推荐阅读
- kubernetes - 为项目部署集成 Kubernetes Helm 模板
- javascript - 未捕获的类型错误:无法读取未定义的属性“单击”
- python - 创建可导入的 Python 3 包/模块
- laravel - 在 Heroku 18 上安装 PDFTK 以在我的 Laravel 应用程序中使用
- laravel-5.4 - (1/1) ErrorException array_merge(): Argument #2 is not an array in ProviderRepository.php line 95
- java - 如何解决“无法解析 AndroidManifest.xml 中的 XML”?
- asp.net-core - 发布到服务器时设置环境为开发
- amazon-web-services - 当我的 aws lambda 函数执行时如何选择弹性 IP
- php - MySQL JOIN 选择用户 id 和他的所有流量添加
- java - 应用程序在某些设备中未收到启动完成的意图