H2 参照完整性约束违反
Posted
技术标签:
【中文标题】H2 参照完整性约束违反【英文标题】:H2 Referential integrity constraint violation 【发布时间】:2019-01-21 12:06:43 【问题描述】:我正在使用 Spring Boot 应用程序的 H2 数据库。我创建了一个帐户服务类,用于保存帐户、帐户类型和客户的数据。请在下面找到代码:
默认构造函数、Getter Setter、使用所有字段的构造函数、toString、hashCode、equals 都存在于以下每个类中。
作为实体的帐户 POJO 以及数据传输对象,即 DTO
@Entity
@Table(name = "ACCOUNT")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Account
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToOne
@JoinColumn(name="account_type_id")
private AccountType accountType;
@Temporal(TemporalType.DATE)
@Column(name = "date_created", unique = true, nullable = false, length = 10)
private Date dateCreated;
@Column(nullable = false)
private double originalCreditAmount;
@Column(nullable = false)
private double balanceAmount;
@Column(nullable = false)
private boolean fullyPaid;
@Column(nullable = false)
private int term;
@Column(nullable = false)
private float rateOfInterest;
@Column(nullable = false)
private boolean escrowAttached;
@Column(nullable = false)
private boolean pmiAttached;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id", nullable = false)
@JsonBackReference
Customer customer;
AcountType POJO 作为实体以及数据传输对象,即 DTO
@Entity
@Table(name = "ACCOUNT_TYPE")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class AccountType
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String accountTypeName;
@Column(nullable = false)
private String accountTypeDescription;
作为实体的客户 POJO 以及数据传输对象,即 DTO
@Entity
@Table(name = "customer")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@Column(nullable = false)
private String socialSecurityNumber;
@Temporal(TemporalType.DATE)
@Column(name = "dob", unique = true, nullable = false, length = 10)
private Date dateOfBirth;
@Column(nullable = false)
private double totalLoanAmount;
@Column(nullable = false)
private int bonusPoints;
@Temporal(TemporalType.DATE)
@Column(name = "customer_since", unique = true, nullable = false, length = 10)
private Date memberSince;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Address> addresses = new HashSet<Address>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Account> accounts = new HashSet<Account>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Contact> contacts = new HashSet<Contact>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Education> education = new HashSet<Education>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Employment> employment = new HashSet<Employment>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Investment> investments = new HashSet<Investment>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
@JsonManagedReference
private Set<Liability> liabilities = new HashSet<Liability>();
@Column()
private int rating;
当我尝试通过 POST 调用创建客户、帐户和帐户类型时:
"customer":
"id": 1,
"firstName": "Jordaya",
"lastName": "Scott",
"dateOfBirth": "1980-04-12",
"totalLoanAmount": 287000,
"bonusPoints": 70000,
"memberSince": "2000-04-11",
"socialSecurityNumber": "449-84-4944",
"rating": 7
,
"accountType":
"id": 2,
"accountTypeName": "Savings A/C",
"accountTypeDescription": "Savings Account"
,
"dateCreated": "2017-01-01",
"originalCreditAmount": 300000,
"balanceAmount": 200000,
"fullyPaid": false,
"term": 30,
"rateOfInterest": 3.25,
"escrowAttached": false,
"pmiAttached": false
失败并出现以下错误。
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKGW84MGPACW9HTDXCS2J1P7U6J: PUBLIC.ACCOUNT FOREIGN KEY(ACCOUNT_TYPE_ID) REFERENCES PUBLIC.ACCOUNT_TYPE(ID) (2)"; SQL statement:
insert into account (account_type_id, balance_amount, customer_id, date_created, escrow_attached, fully_paid, original_credit_amount, pmi_attached, rate_of_interest, term, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
请纠正我对错误的理解。我认为这个错误即将到来,因为客户和帐户类型记录不是在数据库中创建的,因此当帐户被插入数据库时,它无法找到帐户类型 ID,因此会引发此错误。
【问题讨论】:
【参考方案1】:是的,如果不存在具有匹配 ID 的实体,您将违反完整性约束。
如果您想实现相关实体的级联创建,您应该将cascade
添加到您的关系映射中。例如:
@OneToOne(cascade = CascadeType.ALL...)
但即便如此,当您发送具有特定 ID 的 JSON 数据并且它们在 DB 中不存在时,您也会收到此错误。
【讨论】:
我将 cascade = CascadeType.ALL 添加到 Account 类中的 Join Columns(Account Type 和 Customer)中,并再次尝试 POST 请求,但失败并出现错误“将分离的实体传递给持久化:com.microservice。 model.AccountType;" 如果没有执行持久化的代码,很难说出了什么问题,但看起来您正在尝试保存 ID 已设置为特定值的级联帐户类型。您需要将其保留为空。但问题是这是否是你想要的。如果 DB 中存在具有此 ID 的帐户类型,则需要先检索它。以上是关于H2 参照完整性约束违反的主要内容,如果未能解决你的问题,请参考以下文章
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:违反参照完整性约束
Hibernate/H2 @OneToMany 删除子时“违反参照完整性约束”?