【发布时间】:2019-10-25 12:16:33
【问题描述】:
我正在构建我的第一个 Spring Boot 应用程序。我使用 Hibernate 和 H2 内存 DBMS。
我正在尝试构建的是一个代表多个应用商店的 REST API。我有一个名为 App 的实体和另一个名为 Store 的实体。一个商店可以包含许多应用程序,每个应用程序可以包含在多个商店中。但是,应用程序不知道它们包含在哪些商店中。我希望能够相互独立地删除应用程序和商店。仅仅因为商店被删除并不意味着其中的应用程序也应该被删除,反之亦然。应用可以在没有商店的情况下存在,没有应用的商店也可以。
这是我的实体的代码,LpApp 是 App 的实现,LpTemplate 是 Store 的实现:
@Entity
public class LpApp {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, updatable = false)
private Long id;
@NotBlank(message = "An app needs a non-empty name")
@Column(nullable = false, updatable = false, unique = true)
private String appName;
// ... constructors, getters, setters, no further annotations
}
@Entity
public class LpTemplate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, updatable = false)
private Long id;
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "template_apps",
inverseJoinColumns = { @JoinColumn(name = "app_id") },
joinColumns = { @JoinColumn(name = "template_id") })
private Set<LpApp> apps = new HashSet<>();
// ... constructors, getters, setters, no further annotations
}
在我尝试从我的 DBMS 中删除应用程序或商店之前,此方法运行良好。此时我得到一个 org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException。
我得到的异常如下(为简洁起见,我修剪了调用堆栈):
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["APP_ID: PUBLIC.TEMPLATE_APPS FOREIGN KEY(APP_ID) REFERENCES PUBLIC.LP_APP(ID) (3)"; SQL statement:
delete from lp_app where id=? [23503-199]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "APP_ID: PUBLIC.TEMPLATE_APPS FOREIGN KEY(APP_ID) REFERENCES PUBLIC.LP_APP(ID) (3)"; SQL statement:
delete from lp_app where id=? [23503-199]
我显然做错了什么,但我不知道去哪里找。我想我没有正确使用 @ManyToMany 注释,或者它可能是我的用例的错误注释。
非常感谢。
【问题讨论】:
-
我尝试使用您创建的实体并使用 cascade ALL 我能够成功执行删除事务。为更清楚起见,请在您尝试删除的位置发布代码。
-
我使用 org.springframework.data.repository.CrudRepository 中的 void deleteById(ID id)。