The following constellation gives me a org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException
:
The associations:
1 Account (account) <-> (mainBudget) Budget 0..1
0..1 Budget (parentBudget) <-> (subBudget) Budget *
The actual implementation of an Account objects and Budget objects would look like this:
Forwards:
Account -> (mainBudget) Budget -> (subBudget) Budget -> (subBudget) Budget
Backwards:
Budget -> (parentBudget) Budget -> (parentBudget) Budget -> (account) Account
Each Budget in the budget tree (max height 3 as modeled) has the same account associated to it, where the account only has the mainBudget associated.
For the Account.java
:
@Audited
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected long id;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval=true, fetch=FetchType.LAZY)
// Here I also tried mappedBy = "account" with @JoinColumn for the budget (with the exception stated at the end)
@LazyToOne(LazyToOneOption.PROXY)
private Budget mainBudget;
}
...
}
For the Budget.java
:
@Audited
@Entity
public class Budget {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected long id;
@OneToOne(fetch=FetchType.LAZY)
//@JoinColumn(name="account_id") - I tried this but also got an exception (stated below)
private Account account;
@OneToMany(targetEntity = Budget.class, cascade = CascadeType.ALL,
mappedBy = "parentBudget", orphanRemoval=true)
@Fetch(value = FetchMode.SUBSELECT)
private List<Budget> subBudget;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="parentBudget_id")
private Budget parentBudget;
...
}
The in-memory H2 database looks the following (which seems fine to me):
The error message in detail is:
Referential integrity constraint violation: "FKovatioxlljiymn9haxf1yrjs7: PUBLIC.Account FOREIGN KEY(mainBudget_id) REFERENCES PUBLIC.Budget(id) (2259)"; SQL statement:
delete from Budget where id=? [23503-200]
The delete-method looks like this:
@Transactional
public boolean delete(long id, String resource)
throws NoSuchElementException {
List<Budget> objs = getAllById(id, resource); //SELECT * FROM Budget WHERE id=...
if (objs.isEmpty()) {
throw new NoSuchElementException(
"Delete not possible.");
}
router.setDataSource(resource);
for (Budget obj : objs) {
em.remove(obj);
em.flush(); // Here the exception is thrown
}
return true;
}
Why do I get a referential integrity constraint violation exception? The same mappings worked before with EAGER loading.
As stated as comments in the code, if I use mappedBy
for the parent and @JoinColumn
for the child I as suggested here, I get the exception:
org.hibernate.HibernateException: More than one row with the given identifier was found: 50, for class: ...Budget