休眠数据完整性违规异常

时间:2018-08-15 12:12:48

标签: java spring hibernate spring-boot repository

我在 Permission Role 类之间有很多关系。 还有一个 role_permission 表,用于保持角色和权限之间的关系

CREATE TABLE public.role_permissions
(
  role_id bigint NOT NULL,
  permission_id bigint NOT NULL,
  CONSTRAINT role_permissions_pkey PRIMARY KEY (role_id, permission_id),
  CONSTRAINT fkh0v7u4w7mttcu81o8wegayr8e FOREIGN KEY (permission_id)
      REFERENCES public.permission (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fklodb7xh4a2xjv39gc3lsop95n FOREIGN KEY (role_id)
      REFERENCES public.role (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.role_permissions
  OWNER TO postgres;

当我想删除权限时,它会引发以下错误

org.postgresql.util.PSQLException: ERROR: update or delete on table "permission" violates foreign key constraint "fkh0v7u4w7mttcu81o8wegayr8e" on table "role_permissions"
  Detail: Key (id)=(6) is still referenced from table "role_permissions".

这是我的课程实现

package com.nova.stats.client.backend.auth.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.PreRemove;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.HashSet;
import java.util.Set;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(exclude = {"users", "roles"})
@ToString(exclude = {"users", "roles"})
@Entity
public class Permission implements GrantedAuthority {

    @Transient
    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

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

    @NotNull
    @Size(min = 2, max=100, message = "Permission name must be between {min} and {max} characters long")
    @Column(unique = true)
    private String name;

    @NotNull
    @Size(min = 10, max=250, message = "Permission description must be between {min} and {max} characters long")
    @Column
    private String description;

    @Getter(onMethod = @__(@Override))
    @NotNull
    @Size(min = 6, max=100, message = "Permission authority must be between {min} and {max} characters long")
    @Column(unique = true)
    private String authority;

    @Getter(onMethod = @__(@JsonIgnore))
    @ManyToMany(mappedBy = "permissions")
    private Set<Role> roles;

    @Getter(onMethod = @__(@JsonIgnore))
    @ManyToMany(mappedBy = "permissions")
    private Set<User> users;

    public Permission(String name, String description, String authority) {
        this.name = name;
        this.description = description;
        this.authority = authority;
    }
}



package com.nova.stats.client.backend.auth.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.HashSet;
import java.util.Set;

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(exclude = {"users", "permissions"})
@ToString(exclude = {"users", "permissions"})
@Getter
@Setter
@Entity
public class Role implements GrantedAuthority {

    @Transient
    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

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

    @NotNull
    @Size(min = 2, max=100, message = "Role name must be between {min} and {max} characters long")
    @Column(unique = true)
    private String name;

    @NotNull
    @Size(min = 10, max=250, message = "Role description must be between {min} and {max} characters long")
    @Column
    private String description;

    @Getter(onMethod = @__(@Override))
    @NotNull
    @Size(min = 6, max=100, message = "Role authority must be between {min} and {max} characters long")
    @Column(unique = true)
    private String authority;

    @Getter(onMethod = @__(@JsonIgnore))
    @ManyToMany(mappedBy = "roles")
    private Set<User> users = new HashSet<>(0);

    @Getter(onMethod = @__(@JsonIgnore))
    @Setter(onMethod = @__(@JsonProperty("permissions")))
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "role_permissions", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
    private Set<Permission> permissions;

    public Role(String name, String description, String authority, Set<Permission> permissions) {
        this(name, description, authority);
        this.permissions = permissions;
    }

    public Role(String name, String description, String authority) {
        this.name = name;
        this.description = description;
        this.authority = authority;
    }
}

这就是我所需要的;当我要删除任何权限时,必须在 role_permission 表中删除外键,但不能删除相关的 role 。我的意思是,删除权限时,只需删除表权限上的权限和表 role_permission

上的关系

我该怎么办?

2 个答案:

答案 0 :(得分:0)

问题在于,当尝试删除权限时,仍会在用户上引用它。您需要先删除用户或删除用户的权限,然后再从权限表中删除。

要级联删除,您可以尝试以下操作:

@ManyToMany(cascade = CascadeType.ALL, mappedBy = "permissions")
private Set<User> users;

答案 1 :(得分:0)

我在角色类中的用户权限上添加了“ @OnDelete(action = OnDeleteAction.CASCADE)”注释。 并且还在权限类中添加了角色用户 现在,它可以按我的意愿工作

这是一个例子

package com.asd.asd;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(exclude = {"users", "roles"})
@ToString(exclude = {"users", "roles"})
@Entity
public class Permission implements GrantedAuthority {

    @Transient
    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

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

    @NotNull
    @Size(min = 2, max=100, message = "Permission name must be between {min} and {max} characters long")
    @Column(unique = true)
    private String name;

    @NotNull
    @Size(min = 10, max=250, message = "Permission description must be between {min} and {max} characters long")
    @Column
    private String description;

    @Getter(onMethod = @__(@Override))
    @NotNull
    @Size(min = 6, max=100, message = "Permission authority must be between {min} and {max} characters long")
    @Column(unique = true)
    private String authority;

    @Getter(onMethod = @__(@JsonIgnore))
    @ManyToMany(mappedBy = "permissions")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Set<Role> roles;

    @Getter(onMethod = @__(@JsonIgnore))
    @ManyToMany(mappedBy = "permissions")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Set<User> users;

    public Permission(String name, String description, String authority) {
        this.name = name;
        this.description = description;
        this.authority = authority;
    }
}