【问题标题】:Spring Boot (Java) - java.sql.SQLIntegrityConstraintViolationException: Duplicate entry for key another tableSpring Boot (Java) - java.sql.SQLIntegrityConstraintViolationException:键另一个表的重复条目
【发布时间】:2022-11-30 04:18:58
【问题描述】:

我在添加具有角色的用户后插入具有角色的新用户时遇到问题。

我首先创建了一个 ROLE_USER 用户和一个 ROLE_ADMIN 用户。

当我试图用它的角色创建一个新的时,我得到了密钥的重复条目错误。

我该如何解决?

这是下面显示的类

@Entity
@Table(name = "Roles")
@NoArgsConstructor
@Getter
@Setter
public class Role extends IdBasedEntity implements Serializable {

    @Enumerated(EnumType.STRING)
    @Column(length = 20, unique = true)
    private ERole name;

    public Role(ERole name){
        this.name = name;
    }

    public ERole getName() {
        return name;
    }
}

@Entity
@Table(name = "Users")
@Data
@NoArgsConstructor
public class User extends IdBasedEntity implements Serializable {

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

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

    private String password;

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

}

public enum ERole {
    ROLE_USER,
    ROLE_ADMIN
}

@MappedSuperclass
@Getter
@Setter
public class IdBasedEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Integer id;
}

@Entity
@Table(name = "RefreshToken")
@Data
public class RefreshToken extends IdBasedEntity implements Serializable {

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

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

    @Column(nullable = false)
    private Instant expiryDate;
}

这是我的代码 sn-p,如下所示。

@PostMapping("/signup")
    public ResponseEntity<?> registerUser(@RequestBody SignUpRequest signUpRequest) {

        String username = signUpRequest.getUsername();
        String email = signUpRequest.getEmail();
        String password = signUpRequest.getPassword();
        Set<String> strRoles = signUpRequest.getRoles();
        Set<Role> roles = new HashSet<>();

        if(userService.existsByUsername(username)){
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken!"));
        }

        if(userService.existsByEmail(email)){
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already taken!"));
        }

        User user = new User();
        user.setEmail(email);
        user.setUsername(username);
        user.setPassword(encoder.encode(password));

        if (strRoles != null) {
            strRoles.forEach(role -> {
                switch (role) {
                    case "ROLE_ADMIN":
                        roles.add(new Role(ERole.ROLE_ADMIN));
                        break;
                    default:
                        roles.add(new Role(ERole.ROLE_USER));
                }
            });
        }else{
            roles.add(new Role(ERole.ROLE_USER));
        }

        user.setRoles(roles);
        userService.saveUser(user);  // ERROR LINE

        return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
    }

这是我的错误,如下所示。

// Create User
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'ROLE_USER' for key 'roles.UK_ofx66keruapi6vyqpv6f2or37'
// Create Admin
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'ROLE_ADMIN' for key 'roles.UK_ofx66keruapi6vyqpv6f2or37'

【问题讨论】:

    标签: java spring-boot


    【解决方案1】:

    从 User.roles 中删除 CascadeType.ALL。角色只能被引用,不能拥有。

    角色只需要创建和存储一次,最好使用一些数据库脚本。在您的代码中,加载所有可用的角色,将它们放在地图中并向用户添加所需的角色。切勿使用 new Role(...) 创建角色。

    【讨论】:

    • 我删除它然后我得到了这个问题。 org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.microservice.authservice.model.Role
    • 您需要先存储这两个角色,加载它们并将其中一些添加到用户。角色应该建模为 Flightweight 对象:只有一个 ADMIN 角色实例和一个 USER 角色实例。
    • 在创建新用户之前,我已经将 ROLE_ADMIN 和 ROLE_USER 存储在数据库中。
    • 我添加了一段来解决这个问题。
    猜你喜欢
    • 2018-02-20
    • 1970-01-01
    • 2019-05-09
    • 2021-06-10
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    相关资源
    最近更新 更多