Spring 子表未映射到JPA中的OneToMany关系

Spring 子表未映射到JPA中的OneToMany关系,spring,spring-boot,hibernate,spring-security,spring-data-jpa,Spring,Spring Boot,Hibernate,Spring Security,Spring Data Jpa,我试图在用户和角色之间建立一对多关系 一个用户可以有多个角色 下面是用户类的代码 @Entity public class User { @Id private int id; private String name; private String password; private String email; private String phoneNo; @OneToMany( target

我试图在用户角色之间建立一对多关系

一个用户可以有多个角色

下面是用户类的代码

@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       
     
通过Jpa与数据库的角色表连接

public interface RoleRepository extends JpaRepository<Role, Integer> {
    
}

   
     
public interface UserRepository extends JpaRepository<User,Integer>{
    
}

我错在哪里?有人能帮我吗?

使用
save()
时,需要刷新对数据库的更改,请尝试以下操作:

userRepo.saveAndFlush(user);

在下面的控制器方法中,您是否尝试调试传入的请求用户对象

无论如何,我这里有以下几点:

首先,查看您的请求主体,您的角色字段名为
role
,而您的用户对象有一个字段
roles
,因此,我很确定在处理过程中它是
null
,因为它不会在那里被反序列化,因为字段名不匹配。尝试将请求正文更改为以下内容:

{
    "id":101,
    "name": "rahul",
    "password": "456",
    "email": "rahul@gmail.com",
    "phoneNo": "1234561234",
    "roles": [{
        "role":"USER"
    }]
}
其次,如果您检查数据库,角色将被保留,但是您的外键
user\u id
为空。这是意料之中的。您对用户对象执行的级联操作仅意味着(因为您使用了级联类型.ALL),一旦保存用户对象,保存操作也将级联到角色对象,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;   
@OneToMany(mappedBy=“user”,cascade=CascadeType.ALL,fetch=FetchType.LAZY)
私人设定角色;

最后,如果您可以将传入的有效负载包装到DTO,这会更好,因为您不想将您的实体/模型公开给API,但我认为这只是为了您的测试环境。

您可以分享(在服务上)关于如何保存此内容的代码吗?@junbetterway我已经更新了代码。请调查一下。
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
   @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Role> roles;