在Hibernate一对一关系中保存外键的问题

时间:2019-05-18 15:10:08

标签: java spring hibernate jpa

我具有以下一对一的休眠关系:

用户

@Entity
@Table(name=User.TABLE_NAME)
public class User {

    public static final String TABLE_NAME = "user";

    @Id
    @GeneratedValue(generator="hibernate-uuid")
    @GenericGenerator(name="hibernate-uuid", strategy="uuid2")
    @Column(name="id", updatable=false, nullable=false)
    private String id;

    @OneToOne(mappedBy="user", fetch = FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
    private Login login;

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

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

    @Column(name="enabled")
    private boolean enabled;

    @Column(name="startDate", nullable=false)
    @NotNull
    private Date startDate;

    @Column(name="expirationDate", nullable=false)
    @NotNull
    private Date expirationDate;

    // GETTERS AND SETTERS HERE
}

登录

@Entity
@Table(name=Login.TABLE_NAME)
public class Login {
    public static final String TABLE_NAME = "login";

    @Id
    @GeneratedValue(generator="hibernate-uuid")
    @GenericGenerator(name="hibernate-uuid", strategy="uuid2")
    @Column(name="id", updatable=false, nullable=false)
    private String id;

    @OneToOne
    @JoinColumn(name="user", referencedColumnName="id", nullable=false)
    private User user;

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

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

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

    @Column(name="token")
    private String token;

    @Column(name="tokenExpirationDate")
    private Date tokenExpirationDate;

    @Column(name="lastLogin")
    private Date lastLogin;   

 // GETTERS AND SETTERS HERE
}

用户DTO

public class UserDTO {
    private LoginDTO loginDTO = new LoginDTO();

    @Override
    public  User to(User user) {
        user.setFirstName(this.getFirstname());
        user.setLastName(this.getLastname()); 
        loginDTO.setEmail(this.getEmail());
        Login login = loginDTO.to(new Login()); 
        user.setLogin(login); 
        user.setStartDate(this.getStartDate());
        user.setExpirationDate(this.getExpirationDate());
        user.setLogicallyDeleted(this.getLogicallyDeleted()); 
        return company;
    }

    @Override
    public void from(User user) {
        this.setFirstname(user.getFirstName());
        this.setLastname(user.getLastName());
        this.setEmail(user.getLogin().getEmail());
    }

    public LoginDTO getLoginDTO() {
        return loginDTO;
    }

    public void setLoginDTO(LoginDTO loginDTO) {
        this.loginDTO = loginDTO;
    }

}

登录DTO

public class LoginDTO {
    private String email;

    public void from(Login login) {
        this.setEmail(login.getEmail());
    }

    public Login to(Login login) {
        login.setEmail(this.getEmail()); 
        return login;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }

}

REST CONTROLLER

我使用Spring Data,因此本文中不包括Service和Repository类,因为它们很容易解释

@RestController
public class CompanyController extends UserController{

    private static final String  PATH_CREATE_USER = "/user/save"; 

    @Autowired
    private UserService userService;

    @PostMapping(PATH_CREATE_USER)
    public ResponseEntity<?> save(@RequestBody CompanyDTO dto) {
        User user= dto.to(new User());
        user.getLogin().setPassword(dto.getPassword());

        // Password as text for testing purposes.
        user.getLogin().setPasswordHash("haasssshhhhh"); 
        userService.save(company);

        return new ResponseEntity<>("", HttpStatus.CREATED);
    }
}

我发布了Postman的以下数据:

{
    "firstname": "ben",
    "lastname": "moore",
    "email": "example@mail.com",
    "password": "pass",
    "startDate":"2018-06-20T00:00:00",
    "expirationDate": "2018-10-20T00:00:00"
}

我得到的结果是user表中的所有列均按预期方式保存。 login表中的所有列均被保存,但user列为空。我期望user表中的login列将填充user表的主键。

2 个答案:

答案 0 :(得分:1)

我想您只是没有设置用户和登录名之间的相互引用。

在您的数据传输对象中,我看到您在用户上设置登录名,但看不到您在用户上设置登录名的位置。

user.setLogin(login);

我认为您需要

login.setUser(user);

答案 1 :(得分:0)

那么,您以明文形式保存密码吗?

    user.getLogin().setPassword(dto.getPassword());
    user.getLogin().setPasswordHash("haasssshhhhh");

不好。

@OneToOne(mappedBy="user", fetch = FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
private Login login;

这表示Login实体是关系的所有者。这意味着只有Login实体将保留该关系。我没有在代码中的任何地方设置user实体的Login字段。