首页 > 解决方案 > Hibernate Cascade - Hiberate 在子级之前保存父级

问题描述

我想使用 Spring Data JPA 在我的数据库中保存一个新的 UserRegistration 实例。在数据库中,我有“用户”和“权限”表。每次我尝试保存实例时,都会收到错误消息“无法添加或更新子行:外键约束失败”。这是因为表“authorities”包含一个引用“users”的外键。该错误是因为 Hibernate 在插入 UserRegistration 实例之前首先尝试存储权限实例:

Hibernate: 
    insert 
    into
        users
        (email, enabled, password, profilePicture, username) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        authorities
        (authority, username, userid) 
    values
        (?, ?, ?)

用户注册.java:

package main.java.de.ostfalia.seprojekt.database.models;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;

import main.java.de.ostfalia.seprojekt.database.dto.UserRegistrationDTO;

@Entity
@Table(name = "users")
public class UserRegistration {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    @JsonIgnore
    private String password;
    @JsonIgnore
    private boolean enabled;
    private Integer profilePicture;
    private String email;
    @OneToOne(fetch = FetchType.LAZY, optional = false, mappedBy = "user", cascade = CascadeType.ALL)
    private Authority authority;
    @JsonManagedReference
    @ManyToMany
    @JoinTable(name = "userhasfavorite", joinColumns = @JoinColumn(name = "userid"), inverseJoinColumns = @JoinColumn(name = "channelid"))
    private List<Channel> favorites;

    public UserRegistration() {
    }

    public UserRegistration(UserRegistrationDTO dto) {
        this.email = dto.getEmail();
        this.username = dto.getUsername();
        this.password = dto.getPassword();
        this.enabled = dto.isEnabled();
        this.profilePicture = dto.getProfilePicture();
        this.authority = new Authority(id, username, dto.getRole(), this);
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Integer getProfilePicture() {
        return profilePicture;
    }

    public void setProfilePicture(Integer profilePicture) {
        this.profilePicture = profilePicture;
    }

    public String getEmail() {
        return email;
    }

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

    public Authority getAuthority() {
        return authority;
    }

    public void setAuthority(Authority authority) {
        this.authority = authority;
    }

    public List<Channel> getFavorites() {
        return favorites;
    }

    public void setFavorites(List<Channel> favorites) {
        this.favorites = favorites;
    }
}

权威.java:

package main.java.de.ostfalia.seprojekt.database.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

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

    @Id
    @Column(name = "userid")
    private int userID;
    private String username;
    private String authority;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "userid")
    private UserRegistration user;

    public Authority() {
    }

    public Authority(int userID, String username, String authority, UserRegistration user) {
        this.userID = userID;
        this.username = username;
        this.authority = authority;
        this.user = user;
    }

    public int getUserID() {
        return userID;
    }

    public void setUserID(int userID) {
        this.userID = userID;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAuthority() {
        return authority;
    }

    public void setAuthority(String authority) {
        this.authority = authority;
    }
}

保存实体的代码:

@PostMapping
public boolean saveUser(@RequestBody UserRegistrationDTO userToSave) {
    if (roleExists(userToSave.getRole())) {
        UserRegistration user = new UserRegistration(userToSave);
        uRepo.saveAndFlush(user);
        return true;
    }
    return false;
}

我现在的问题是:如何在使用 CascadeTypes 插入权限实例之前保存 UserRegistration 实例?

感谢您阅读这个问题。我期待着解决这个问题。

标签: javaspringhibernatewebcascade

解决方案


推荐阅读