【问题标题】:Spring JPA Assosiation entity create the same recordSpring JPA 关联实体创建相同的记录
【发布时间】:2019-05-24 02:38:02
【问题描述】:

我正在设置 Spring Boot 应用程序 尝试制作“添加用户菜单”,每次我发布这样的 JSON 数据时:

MySQL 总是在 role_table 中创建新的 ADMIN 记录。

我的意图是只在role_table 中为user_table 中的多个用户创建一个管理记录(一对多)

到目前为止,我已经尝试修改几个 Spring JPA Annotation 不同类型的获取、关联和配置。

到目前为止,我的 MySql 数据库表上的结果如下:

role_table.    user_table
id.   role.    id    username  role_id
1    Admin      1    Tony      1
2.   User       2.   Buddy.    2
3.   Guest.     3.   Liaska.   3
4.   Admin      4.   Roy.      5
5.   Admin.     5.   Subrey.   4
6.   User.      6.   Alhanus.  7
7.   Guest      7.   Rsidi.    6

我希望 MySql 表中的结果如下所示:

role_table.    user_table
id.   role.    id    username  role_id
1    Admin      1    Tony      1
2.   User       2.   Buddy.    2
3.   Guest.     3.   Liaska.   3
                4.   Roy.      1
                5.   Subrey.   3
                6.   Alhanus.  1
                7.   Rsidi.    1

谢谢大家

这样的角色类:

public class Role implements Serializable{


@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id", length=8, unique = true)
private int id;

@Column(name = "role",nullable = false, unique = false)
private String role;

@OneToMany(mappedBy="role", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
@Fetch(value = FetchMode.SUBSELECT)
private List<User> user = new ArrayList<User>();}

这样的用户类:

public class User implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="user_id", length=8, unique = true)
private int user_id;

@Column(name = "username", nullable = false, unique = true)
private String username;

@Column(name = "password", nullable = false, unique = true)
private String password;



@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Role role;}

这样的AdminController类:

public class AdminController {

private static final Logger LOGGER = LoggerFactory.getLogger(AdminController.class);


@Autowired
private UserRepository userRepository;

 @Autowired
  private RoleRepository roleRepository;

 private Role role = new Role();

@Autowired
 private BCryptPasswordEncoder passwordEncoder;

@PreAuthorize("hasAnyRole('ADMIN')")
@PostMapping("/admin/add")
 public String addUserByAdmin(@RequestBody User user){

    String pwd = user.getPassword();

    String encryptedPwd = passwordEncoder.encode(pwd);

    user.setPassword(encryptedPwd);



    if(userRepository.findByUsername(user.getUsername())==null){

        userRepository.save(user);

    } else {

         return "user already exist
    }
    return "user added successfully ... ";


}

【问题讨论】:

  • 如何保存角色。在 AdminController 中,我只能看到创建了一个新的角色对象。它在哪里与用户相关联?你能添加那部分代码吗
  • 我只是简单地使用名为 postman 的 App 发布 JSON 对象,然后 spring 处理所有内容,我不创建链接用户的东西,spring boot 自动处理它,我发布的 JSON 数据看起来像这样的“用户名”:“Frantu ", "密码": "Pshycho8k8ss", "角色" : {"角色":"管理员"}
  • 没错,因为您只是将角色传递为 ADMIN 而没有主键。它被视为新记录,您在 DB 中获得多个角色。
  • 我现在明白了……谢谢你们。将 cascadeType.ALL 更改为 cascadeType.MERGE 工作...使用这样的 JSON 数据 User {id=0, username = Frantu, password= Pshycho8k8ss , role = {id=0, role=ADMIN }

标签: java json spring jpa


【解决方案1】:

问题在于初始化role 对象的持久性。在这里,您将在 JSON 中获取用户对象,如下所示:

 {"username": "Frantu", "password": "Pshycho8k8ss", "role" : {"role":"ADMIN"} }

没有为角色实体初始化 id 字段。

所以你的用户对象会像

User {id=0, username = Frantu, password= Pshycho8k8ss , role = {id=0, role=ADMIN }

您没有在此处传递role.id,因此 JPA 将为每个新请求创建一个带有新主键的新记录。

要解决此问题,首先,使用 role 属性从 DB 中获取 role(如果存在)并将其设置为 User 对象。

Role dbRole = roleRepository.findByRole(user.getRole().getRole());
if(dbRole!=null){
     user.setRole(dbRole);
}

userRepository.save(user);

【讨论】:

  • 用户 {id=0, username = Frantu, password= Pshycho8k8ss , role = {id=0, role=ADMIN } 真的对我有用...在 cascadeType.ALL 中额外更改为 cascadeType。合并...感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多