Hibernate Cascade DELETE OneToMany does not work. Referential integrity constraint violation - java

I have a class Webtoon that contains a list of Episode. It is a one direction relation.
#OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
#CollectionTable(name= "list_of_episodes")
List<Episode> listOfEpisodes = new ArrayList<>();
In my Unit test, I created a Webtoon object, then added an episode in the list listOfEpisodes.
When I try to delete the Episode using the Episode repository
this.episodeRepo.delete(episode);
I got the error :
violation de contrainte: "FK50GHKTDAXMN68TBU6KAYVUX9S:
PUBLIC.LIST_OF_EPISODES FOREIGN KEY(LIST_OF_EPISODES_ID) REFERENCES
PUBLIC.EPISODE(ID) (3)"
Referential integrity constraint violation: "FK50GHKTDAXMN68TBU6KAYVUX9S: PUBLIC.LIST_OF_EPISODES FOREIGN
KEY(LIST_OF_EPISODES_ID) REFERENCES PUBLIC.EPISODE(ID) (3)"; SQL
statement:
delete from episode where id=? [23503-200]
Why hibernate can't remove this object and update the list in Webtoon class ?

Try to change FetchType from EAGER to LAZY

Referential integrity is a property of data stating that all its references are valid. In the context of relational databases, it requires that if a value of one attribute (column) of a relation (table) references a value of another attribute (either in the same or a different relation), then the referenced value must exist.
From the error PUBLIC.LIST_OF_EPISODES FOREIGN KEY(LIST_OF_EPISODES_ID) REFERENCES PUBLIC.EPISODE(ID) you can clearly see that PUBLIC.EPISODE(ID) is referenced as a foreign key in PUBLIC.LIST_OF_EPISODES table so you cannot delete a parent unless you delete a child element.
Try using #JoinColumn instead of using #CollectionTable(name= "list_of_episodes")

To correct this issue, I first changed the uni-directional relation to bi-directional.
In Webtoon I have :
#OneToMany(cascade = CascadeType.ALL, mappedBy="webtoon", orphanRemoval = true)
#CollectionTable(name= "list_of_episodes")
List<Episode> listOfEpisodes = new ArrayList<>();
In Episode, I added a webtoon attribute
#ManyToOne(fetch= FetchType.LAZY)
#JoinColumn(name="webtoon_id")
Webtoon webtoon;
Because, it is lazy...I could not get the list as if I'm using eager, so I added a join select in my repository. And also when I delete, I have the cascade delete.

Related

Hibernate java ORA-02292: integrity constraint violated - child record found Course with Review

When I want to delete any course with respect to its id, review related with this course can also be deleted. But there is an insue appeared on the console.
Hibernate java ORA-02292: integrity constraint violated - child record found
Course.java
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL,mappedBy="course")
private Set<Review> reviews = new HashSet<Review>();
Review.java
#ManyToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
#JoinColumn(name = "COURSE_ID", nullable = false)
private Course course;
I tried to use orphanRemoval=true but nothing changed.
How can I fix the issue?
Specify the foreign key constraint in the child table as ON DELETE CASCADE. You'll need to invoke EntityManager.clear() after calling EntityManager.remove(course) as the persistence context needs to be refreshed - the child entities are not supposed to exist in the persistence context after they've been deleted in the database.
#ManyToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
#JoinColumn(name = "COURSE_ID", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
private Course course;
To assign action ON DELETE CASCADE in the related foreign key. In my question , I defined a foreign key to make a connection between Course and Review with a feature ON DELETE CASCADE. In this way, reviews related with course can be deleted when the course can be deleted.
Try this
#OneToMany(mappedBy="course", orphanRemoval=true)

Orphan removal with #Where clause

I have a hierarchical structure. Some children are hidden so I have #Where clause:
#OneToMany(fetch = FetchType.LAZY, orphanRemoval = true)
#org.hibernate.annotations.Where(clause = "hidden=false")
private List<Element> children;
But when I want to remove the whole sub-structure (including hidden children) by deleting parent node, hibernate seems to skip hidden children and i get db exception:
org.postgresql.util.PSQLException: ERROR: update or delete on table "xxx" violates foreign key constraint "yyy_yyy_id_fkey" on table "zzz"
Does hibernate have some method of dealing with it?

#PrimaryKeyJoinColumn with name of foreign key

Under hibernate-jpa-api-2.0, can i specify the name of the foreign key using #PrimaryKeyJoinColumn with oneToOne relation ?
I tried the folowing but it doesn't seem to work.
#OneToOne(optional = false, fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn(name = "CARID")
#ForeignKey(name = "FK_CAR_CORP")
public CarEntity getCar() {
return car;
}
There are two #ForeignKey annotations can be used:
org.hibernate.annotations.ForeignKey (Hibernate annotation)
javax.persistence.ForeignKey (JPA annotation)
Hibernate 4 (even the last version) sometimes doesn't process, probably cause of bug, javax.persistence.ForeignKey annotation.
For example, with Hibernate 4.3.11 we should use org.hibernate.annotations.ForeignKey on the #OneToMany part of unidirectional association. And we can use javax.persistence.ForeignKey on the #ManyToOne part of bidirectional association.
So you can try to use Hibernate org.hibernate.annotations.ForeignKey annotation.
The mappedBy attribute is only necessary for a bidirectional relationship, this element can be omitted on the annotation. It is used on the source entity to point back to a field on the target entity that defines the relationship (contains #JoinColumn).
The #JoinColumn annotation should be placed upon the billSimpleEntry field to define the column that should be used to join the two tables. In the case of a OneToOne the following applies:
If the join is for a OneToOne or ManyToOne mapping using a foreign key mapping strategy, the foreign key column is in the table of the source entity or embeddable.
Here is a code example:
#OneToOne(cascade=CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name="id") // use actual column name
private ClassName className; // use class name
I don't think #ForeignKey will work for hibernate-jpa-api-2.0, as per doc it's release in 2.1
Since:
Java Persistence 2.1
here is doc

JPA: implicit cascades for relationships mapped as #ManyToMany #JoinTable?

I have the following mapping:
#Entity
#Table(name = "Prequalifications")
public class Prequalification implements Serializable
{
...
#ManyToMany
#JoinTable(name = "Partnerships", joinColumns = #JoinColumn(name = "prequalification_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "company_id", referencedColumnName = "id"))
private Set<Company> companies;
...
}
In a #ManyToMany + #JoinTable mapped relationship, isn't it kind of implicit that the association (link) entities (here Partnerships) are automatically persisted, removed, etc. even though
by default, relationships have an empty cascade set
? The above quote was taken from "Pro JPA 2, by Mike Keith".
Executing
em.merge(prequalification);
on the above entity does persist the associated partnerships without any cascade types specified.
Am I correct that this implicit cascade has to be performed? This isn't mentioned anywhere I looked...
The rows in the join table will be inserted/deleted as part of the owning Entity (if bi-directional the side without the mappedBy). So if you persist or remove or update the Prequalification the join table rows will also be inserted or deleted.
The target Company objects will not be cascaded to. So on remove() they will not be deleted, if the list is updated they will not be deleted unless orphanRemovla is set. Persist should also not be cascaded, but what happens when you have references to "detached" objects is somewhat of a grey area. Technically an error should be thrown, because the object is new and the relationship was not cascade persist. It may also try to insert and get a constraint error. It should not cascade the persist, although your object model is technically in an invalid state, so what occurs may depend on the provider.
Wanted to add a comment, but don't have enough rep for it.
I had the same question as #D-Dá´™um: "Where in the docs can we find a reference to this behaviour?"
I found it in the Hibernate docs (many-to-many).
If you scroll just a bit just below the code example there, you will find:
When an entity is removed from the #ManyToMany collection, Hibernate simply deletes the joining record in the link table. Unfortunately, this operation requires removing all entries associated with a given parent and recreating the ones that are listed in the current running persistent context.
Where the "link table" refers to the "join table".
Hope this helps.

Deleting JPA object fails due to foreign key constraints?

Why would the following query fail due to a foreign key constraint? There is no other way for me to delete the associated data that I am aware of.
Query query=em.createQuery("DELETE FROM Person");
query.executeUpdate();
em.getTransaction().commit();
The I believe the offending relationship causing the problem is the activationKey field:
2029 [main] ERROR org.hibernate.util.JDBCExceptionReporter - integrity
constraint violation: foreign key no action; FKCEC6E942485388AB
table: ACTIVATION_KEY
This is what I have now:
#Entity
#Table(name="person")
public class Person implements Comparable<Person> {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private long id = 0;
#ElementCollection
#Column(name = "activation_key")
#CollectionTable(name = "activation_key")
private Set<String> activationKey = new HashSet<String>();
}
Why would the following query fail due to a foreign key constraint?
It looks like your bulk delete query is not deleting the entries from the collection table, hence the FK constraint violation.
And while the JPA spec explicitly writes that a bulk delete is not cascaded to related entities:
4.10 Bulk Update and Delete Operations
...
A delete operation only applies to
entities of the specified class and
its subclasses. It does not cascade to
related entities.
That's not exactly your case and I think that what you want to do should be supported.
You're probably facing one of the limitation of Hibernate's bulk delete, see for example:
HHH-3337 - Hibernate disregards #JoinTable when generating bulk UPDATE/DELETE for a self-joined entity
HHH-1917 - Bulk Delete on the owning side of a ManyToMany relation needs to delete corresponding rows from the JoinTable
I suggest raising an issue.
Workaround: use native queries to delete the collection table and then the entity table.

Categories

Resources