Hibernate: Issue with OnDelete Annotation - java

Hello
I have the following two entities
#Entity
public class DocumentCollection {
#Id
#GeneratedValue
private Long id;
#OneToMany(targetEntity=Document.class,mappedBy="documentCollection",cascade=javax.persistence.CascadeType.ALL)
#OnDelete(action = OnDeleteAction.CASCADE)
#Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Document> documents;
...
}
And:
#Entity
public class Document {
#Id
#GeneratedValue
private Long id;
#ManyToOne
private DocumentCollection documentCollection;
...
}
When a DocumentCollection gets deleted, all referenced documents should be deleted too.
But I'm getting this error:
Cannot delete or update a parent row: a foreign key constraint fails (`tms_db`.`document`, CONSTRAINT `FK3737353BEB85533C` FOREIGN KEY (`documentCollection_id`) REFERENCES `documentcollection` (`id`))
I also tried putting the #OnDelete Annotation in the document class but didn't work.
So what am I missing? For your information, I'am using Hibernate 3.6.0.Final.
UPDATE: I did a mysql schema dump and noticed that there is no ON DELETE CASCADE statement in the document table schema. Hibernate only generates the foreign key constraints, which leads to the mentioned error. Has anybody an idea why hibernate does NOT generate the "ON DELETE CASCADE" statement?
Hope, somebody can help me
thx

#OnDelete annotation affects the way Hibernate generates database schema. If your schema is not generated by Hibernate, or haven't been updated after adding this annotation, it wouldn't work correctly.
If you want to use manually created database schema with #OnDelete(action = OnDeleteAction.CASCADE), you should manually define foreign key constraint in your schema as on delete cascade.

Related

Add a Foreign key relation to existing table using hibernate in spring boot application

I am using hibernate to creating and updating tables. Now i am trying to add relation to a new table from an existing table and i am receiving an error.
ItemEntity.java
#Getter
#Setter
#Table(name="Item")
#Entity(name="ItemEntity")
public class ItemEntity {
//item_id
//item_name
}
The above table already have some entries. Now i am trying to add relation between new table(Cart) as a ManyToOne Relationship like below.
#ManyToOne
#JoinColumn(name="cart_id", nullable=false)
private Cart cart;
New Entity (CartEntity.java)
#Getter
#Setter
#Table(name="Cart")
#Entity(name="CartEntity")
public class CartEntity {
//cart_id
#OneToMany(mappedBy="cart")
private Set<Items> items;
}
As ItemEntity already has some entries in it, i am not able to add the relation like the above. Any help is appreciated. I am getting the below Error when trying to add the relation:
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table Item add constraint F9c5xc7cj5432ua6x332x40 foreign key (item_id) references cart" via JDBC Statement.
Thanks in Advance!

#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

How to cascade delete entities with unidirectional 'ManyToOne' relationship with JPA

I have two entity classes 'User' and 'Department' with unidirectional 'ManyToOne' relationship as below.
public class User{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "DEPARTMENT_ID", nullable = true)
private Department department;
}
public class Department{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
If I want to delete some users and cascade remove the referenced departments if not any user references the department, is there any features of JPA to use please?
You can use CascadeType.DELETE, however this annotation only applies to the objects in the EntityManager, not the database. You want to be sure that ON DELETE CASCADE is added to the database constraint. To verify, you can configure JPA to generate a ddl file. Take a look at the ddl file, you'll notice that ON DELETE CASCADE is not part of the constraint. Add ON DELETE CASCADE to actual SQL in the ddl file, then update your database schema from the ddl. This will fix your problem .
This link shows how to use ON DELETE CASCADE on for CONSTRAINT in MySQL. You do this on the constraint. You can also do it in a CREATE TABLE or ALTER TABLE statement. It's likely that JPA creates the constraint in an ALTER TABLE statement. Simply add ON DELETE CASCADE to that statement.
Note that some JPA implementors do provide a means for this functionality.
Hibernate does supply this functionality using the #OnDelete annotation.
You can tell hibernate to delete 'orphan' entries with;
#Cascade({ org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })

How to do bulk delete in JPA when using Element Collections?

I am having trouble working out how to do a bulk delete of a Person object using JPA, when the Person objects contain data stored using an #ElementCollection. Any ideas on how to do this would be much appreciated.
#Entity
#Table(name="at_person")
public class Person implements Comparable<Person> {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private long id = 0;
#Column(name="name", nullable = true, length = 128)
private String name = "";
#ElementCollection
#Column(name = "email")
#CollectionTable(name = "person_email", joinColumns = #JoinColumn(name = "person_id"))
private Set<String> email = new HashSet<String>();
}
What I am doing at the moment is this, and it fails with a foreign key constraint error:
Query query=em.createQuery("DELETE FROM Person");
Caused by: java.sql.SQLException: integrity constraint violation:
foreign key no action; FKCEC6E942485388AB table: PERSON_EMAIL
If it can be a pure JPA annotation rather than a Hibernate annotation that would be a bonus!
I'll let you interpret the part of the JPA 2.0 specification that mentions that a bulk delete operation is not cascaded:
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.
And the fact is that Hibernate won't cascade a delete to a collection table either. This has been reported in HHH-5529 and the suggested approaches are:
You could also (a) clean up the collection table yourself or (b) use cascading foreign keys in the schema.
In other words, (a) use native SQL or (b) use a cascade delete constraint at the database level - and you'll have to add it manually, I don't think you can use #OnDelete with the #ElementCollection annotation (same story as HHH-4301 IMO).

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