【问题标题】:How to remove a user and the refresh tokens that are referencing it?如何删除用户和引用它的刷新令牌?
【发布时间】:2021-10-09 11:05:57
【问题描述】:

我有两个模型(用户和 RefreshToken)。当我尝试通过 API 删除用户时,我收到此错误:

(id)=(5) 仍然从表“refreshtoken”中引用

这是我的User 模型:

@Entity
@Table( name = "users", 
    uniqueConstraints = { 
        @UniqueConstraint(columnNames = "username"),
        @UniqueConstraint(columnNames = "email") 
    })
    public class User implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

        @NotBlank
        @Size(max = 20)
        private String username;

        @NotBlank
        @Size(max = 50)
        @Email
        private String email;

        @NotBlank
        @Size(max = 120)
        private String password;

        @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable( name = "user_roles", 
            joinColumns = @JoinColumn(name = "user_id"), 
            inverseJoinColumns = @JoinColumn(name = "role_id"))
        private Set<Role> roles = new HashSet<>();

这是我的refreshToken 模型:

@Entity(name = "refreshtoken")
public class RefreshToken {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

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

    @Column(nullable = false, unique = true)
    private String token;

    @Column(nullable = false)
    private Instant expiryDate;

    //getters and setters

当我想删除一个用户时,我希望在数据库中也删除属于该用户的刷新令牌。我搜索并发现我应该使用 cascade 或 orphanRemoval 但我不明白如何在这里使用它们。

如果有人能提供帮助,我将不胜感激。

【问题讨论】:

    标签: java jpa orm one-to-one refresh-token


    【解决方案1】:

    通过在用户中添加RefreshToken 并使用CascadeType.ALL 来建立双向关系。

    例子:

    
    @Entity
    @Table( name = "users", 
        uniqueConstraints = { 
            @UniqueConstraint(columnNames = "username"),
            @UniqueConstraint(columnNames = "email") 
        })
        public class User implements Serializable {
            ....
            @OneToOne(mappedBy = "user")
            private RefreshToken refreshToken;
            ....
       }
    

    RefreshToken 实体中:

    
    @Entity(name = "refreshtoken")
    public class RefreshToken {
       
            ....
            @OneToOne(cascade = CascadeType.ALL)
            @JoinColumn(name = "user_id", referencedColumnName = "id")
            private User user;
            ....
        }
    

    【讨论】:

      【解决方案2】:

      您需要指定从用户到RefreshToken@OneToOne 关联。

      @Entity
      class User {
      
        @OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
        private RefreshToken token;
      
      }
      
      @Entity
      class RefreshToken {
      
          @OneToOne
          @JoinColumn(name = "user_id")
          private User user;
      
      }
      

      阅读本文以了解与用户一起删除令牌的方法: JPA orphan removal does not work for OneToOne relations

      请记住,您可以在用户端使用 @ManyToOne 对一对一关联进行建模(因此您将在用户端使用 FK,而不是在令牌端)。可能您会希望在 users 表中为令牌 FK 添加唯一约束。

      您也可以在用户端使用@OneToOne@JoinColumn。所以令牌中不会有User FK。

      使用Long id 代替RefreshToken 中的long id

      【讨论】:

        【解决方案3】:

        要使用级联选项,您应该通过添加 RefreshToken 来更新用户类,这样当用户被删除时,操作可以级联到 RefreshToken。

        @OneToOne(cascade=CascadeType.ALL, orphanRemoval = true)
        private RefreshToken refreshToken = RefreshToken;
        

        这样,当用户被删除时,与他相关的 RefreshToken 也会被删除。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-06-12
          • 2014-05-01
          • 2016-09-23
          • 2016-03-13
          • 2022-11-17
          • 1970-01-01
          • 2020-07-12
          • 1970-01-01
          相关资源
          最近更新 更多