【问题标题】:Hibernate Data Integrity Violation ExceptionHibernate 数据完整性违规异常
【发布时间】:2018-08-15 12:12:48
【问题描述】:

PermissionRole 类之间存在多对多关系。 并且有一个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。我的意思是当删除权限时,只删除表 permission 上的权限和表 role_permission

上的关系

我该怎么办?

【问题讨论】:

  • 您也必须从 Role 中删除 Permission 对象引用。
  • 你到底是什么意思?
  • 看看这个answer
  • 为什么不将外键 (permission_id) 更改为 ON DELETE CASCADE?

标签: java spring hibernate spring-boot repository


【解决方案1】:

问题是当试图删除一个权限时,它仍然被用户引用。在从权限表中删除之前,您需要先删除用户或删除其权限。

要在级联中删除,你可以试试这个:

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

【讨论】:

    【解决方案2】:

    我在角色类中的UserPermission上添加了“@OnDelete(action = OnDeleteAction.CASCADE)”注解 并且还在Permission class中添加了RoleUser 现在,它可以按我的意愿工作了

    这是一个例子

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-03
      • 2013-03-31
      • 2015-08-25
      • 2013-11-27
      • 2020-04-22
      • 1970-01-01
      • 2014-03-17
      • 2015-05-07
      相关资源
      最近更新 更多