我有一个带有字符串列表的实体("Saunoja")。当试图从H2-console中删除一个Saunoja时,会发生以下错误:
Referential integrity constraint violation: "FKIL684UE3YHG0N80RMHVIFQTA0: PUBLIC.SAUNOJA_ROLES FOREIGN KEY(SAUNOJA_ID) REFERENCES PUBLIC.SAUNOJA(ID) (1)"; SQL statement: DELETE FROM "PUBLIC"."SAUNOJA" WHERE "ID"=? [23503-200]
我对Saunoja实体的另一个属性有同样的问题,但它得到了修复,回答了之前问过的一个类似的问题。因为这个属性是一个由另一个实体组成的列表,而@OneToMany关系是有问题的,解决方案是添加一个@OnDelete(action = OnDeleteAction.CASCADE),但在这个实例中它不起作用,因为它不是一个实际的@OneToMany关系。
我的实体看起来像这样:
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Saunoja extends AbstractPersistable<Long> implements Comparable<Saunoja> {
private String username;
private String password;
private String firstName;
private String lastName;
@Cascade(org.hibernate.annotations.CascadeType.ALL)
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
private List<String> roles;
private LocalDateTime created;
private Long profilepictureId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author")
@OnDelete(action = OnDeleteAction.CASCADE)
private List<Photo> photos;
@Override
public int compareTo(Saunoja other) {
return username.compareToIgnoreCase(other.username);
}
}
创建一个单独的表用于持久化角色。这个表名为SAUNOJA_ROLES。可能与字符串列表的注释有关…?
我已经试过这样做了(以及各种组合):
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn
private List<String> roles;
似乎将对象属性注释为ElementCollection使得很难或不可能像通常那样直接删除所讨论的实体:https://hibernate.atlassian.net/browse/HHH-5528.
而ElementCollection是处理List of Strings的方法。
因此,我对这个问题的解决方案是在删除实体之前以编程方式擦除List。似乎没有办法将删除级联到列表中。无论如何,这解决了我现在的问题:@PreAuthorize("hasAuthority('GOD')")
public void deleteSaunoja(String username) {
Saunoja saunoja = saunojaRepository.findByUsername(username);
if (saunoja != null) {
saunoja.getRoles().clear();
saunojaRepository.save(saunoja);
saunojaRepository.delete(saunoja);
deletedSaunojaRepository.save(new DeletedSaunoja(username, LocalDateTime.now()));
}
}