首页 > 解决方案 > 子表在 JPA 中的 OneToMany 关系中没有映射

问题描述

我正在尝试在UserRole之间建立一对多的关系。

一个用户可以有多个角色。

这是用户类的代码

@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 
  

我哪里错了?任何人都可以帮助我吗?

标签: springspring-boothibernatespring-securityspring-data-jpa

解决方案


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

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

首先,查看您的请求正文,您的角色字段被命名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,但我认为这仅适用于您的测试环境。


推荐阅读