问题是,当我想删除用户时,我在Spring Boot中会遇到这样的错误:
java.sql.SQLIntegrityConstraintViolationException:无法删除或更新父行:外键约束失败(
32506632_pam
。badge
,CONSTRAINTFK4aamfo6o0h5ejqjn40fv40jdw
外国关键字(user_id
)参考user
(id
) )
我猜我需要以级联方式删除数据。因此,我已经将CascadeType.REMOVE值放置到@ OneToOne注释中,但这是行不通的:
徽章实体
@Entity
@Data
@Table(name = "badge")
@AllArgsConstructor
@NoArgsConstructor
public class Badge {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonManagedReference
@ManyToMany(mappedBy = "badges", fetch = FetchType.LAZY)
private List<Reader> readers;
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval=true)
@JoinColumn(name = "user_id")
private User user;
private String number;
@Lob
@Basic(fetch = FetchType.LAZY)
private byte[] photo;
}
用户实体
@Entity
@Data
@Table(name = "user")
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String lastname;
private String pesel;
private String email;
private String telephone;
private Integer age;
private String gender;
}
读者实体
@Entity
@Data
@Table(name = "reader")
@AllArgsConstructor
@NoArgsConstructor
public class Reader {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonBackReference
@ManyToMany(fetch = FetchType.LAZY)
private List<Badge> badges;
private String department;
private String room;
private Boolean status;
}
加载初始数据的类
@Component
public class DataLoader implements ApplicationRunner {
@Autowired
private UserService userService;
@Autowired
private BadgeService badgeService;
@Autowired
private ReaderService readerService;
@Override
public void run(ApplicationArguments args) throws Exception {
User user1 = new User(null, "Jan", "Kowal", "11111111111", "[email protected]", "+48111111111", new Integer(23), "male");
userService.saveUser(user1);
Reader reader1 = new Reader(null, null, "Warehouse", "207A", new Boolean("true"));
Badge badge1 = new Badge(null, Arrays.asList(reader1), user1, "738604289120", null);
badgeService.saveBadge(badge1);
reader1.setBadges(Arrays.asList(badge1));
readerService.saveReader(reader1);
}
}
用于删除用户的端点-它使用存储库来扩展CrudRepository并使用默认的删除行为。
@DeleteMapping("/deleteUserById/{id}")
private void deleteUserById(@PathVariable Long id) {
userService.deleteUserById(id);
}
我的目标是删除用户和与其关联的徽章,然后删除reader_badges表中的行。
如果要从用户删除相关的Badge实例,则必须将CascadeType.REMOVE添加到用户关系规范中,当然还要在User中声明Badge实例变量/属性。课。
详细说明当您尝试从表中删除用户实例时发生错误,因为它是父行。徽章行中的FK约束“ user_id”将在每次编辑关系时查看该关系上的数据完整性。删除User实例将导致Badge实例无法在User表中找到他的相关主键“ id”,因此约束消失了,这就是异常的原因。
实际上映射到数据库的关系是:徽章取决于用户
不是相反。
因此,如果您删除已声明的用户
cascade = CascadeType.REMOVE
在级联策略中,将达到目的。但事实并非相反。因为级联策略用于将级联删除从父级“级联”到子级(依赖/依赖于父级的实体)。因此,在您的情况下,从用户到徽章。
因为徽章实际上是您关系中的弱者。Obs:如果您不需要相反的行为,即在删除Badge之后删除User实例,则可以轻松地删除该行:
cascade = CascadeType.REMOVE
来自徽章级联策略。