Spring Boot 相关实体未正确保存

问题描述 投票:0回答:1

通过创建

User
Authority
类来实现身份验证,如下所示:

用户

package com.blog.blog.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "authorities")
public class Authority {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

用户

package com.blog.blog.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.persistence.*;
import org.hibernate.annotations.CreationTimestamp;

import java.util.Set;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private int id;

    private String name;

    private String email;

    @Column(name = "mobile_number")
    private String mobileNumber;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String pwd;

    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private String createdAt;

//    @JsonIgnore
    @OneToMany(mappedBy="user",fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Authority> authorities;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getMobileNumber() {
        return mobileNumber;
    }

    public void setMobileNumber(String mobileNumber) {
        this.mobileNumber = mobileNumber;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public Set<Authority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Set<Authority> authorities) {
        this.authorities = authorities;
    }

}

我的控制器保存

User
看起来像这样:

package com.blog.blog.controller;
// ...

@RestController
public class RegistrationController {

    private final UserRepo userRepo;

    public RegistrationController(UserRepo userRepo) {
        this.userRepo = userRepo;
    }

    @PostMapping("/register")
    public ResponseEntity<User> register(@RequestBody User userRequest){


        User u = userRepo.save(userRequest);
        return new ResponseEntity<>(u, HttpStatus.CREATED);
    }
}

这是 JSON 有效负载:

{
    "name": "aa",
    "email": "[email protected]",
    "mobileNumber": 1999,
    "pwd": "password",
    "authorities": [        
        { "name": "ROLE_ADMIN"}
    ]
}

问题:

在数据库中填充

User
记录,但
Authority
记录与
User
记录不关联:

这就是它的样子:

当我检查日志时,我看到插入

Authority
记录时
user_id
指向
null

2024-02-04T12:00:57.803+05:30 TRACE 661939 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter (1:INTEGER) <- [4]
2024-02-04T12:00:57.810+05:30 DEBUG 661939 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into authorities (name,user_id) values (?,?)
2024-02-04T12:00:57.810+05:30 TRACE 661939 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter (1:VARCHAR) <- [ROLE_ADMIN]
2024-02-04T12:00:57.810+05:30 TRACE 661939 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter (2:INTEGER) <- [null]
java spring spring-boot hibernate spring-mvc
1个回答
0
投票

当您有双向

@OneToMany
关联时,关联双方都需要同步以确保数据一致性。这意味着子实体必须了解父实体才能设置正确的外键 (
user_id
)。

register
方法应更改为以下内容:

public ResponseEntity<User> register(@RequestBody User userRequest){
    userRequest.getAuthorities().forEach(i -> i.setUser(userRequest));
    User u = userRepo.save(userRequest);
    return new ResponseEntity<>(u, HttpStatus.CREATED);
}

通常,在父端定义两个实用方法,如下所示,自动同步子端。

public void addAuthority(Authority authority) {
    authorities.add(authority);
    authority.setUser(this);
}
 
public void removeAuthority(Authority authority) {
    authorities.remove(authority);
    authority.setUser(null);
}

供参考:映射 JPA 和 Hibernate

@OneToMany
关系的最佳方式

© www.soinside.com 2019 - 2024. All rights reserved.