I have two tables with OneToMany relation
class ServiceProvider {
...
#OneToMany(fetch=FetchType.EAGER,mappedBy="serviceProvider",
cascade={CascadeType.ALL,CascadeType.REMOVE},orphanRemoval = true)
#OnDelete(action=OnDeleteAction.CASCADE) private
List serviceCenters; ...
}
class ServiceCenterDetails {
... //bi-directional many-to-one association to
ServiceProviderDomainMap #ManyToOne
#JoinColumn(name="SERVICE_PROVIDER_ID") private ServiceProvider
serviceProvider;
...
}
I am trying to delete provide row. But i am getting below error:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (fixoline.service_center_details, CONSTRAINT FK_qvahoxeovx9vmwl6mcu2c0lyw FOREIGN KEY (SERVICE_PROVIDER_ID) REFERENCES service_provider (ID))
below is the way i am trying
String hql = "DELETE FROM ServiceProvider WHERE id = :providerId";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
query.setParameter("providerId",providerId);
int result = query.executeUpdate();
could someone pls help resolving it?
There are two tings,
Why you are using #OnDelete when you using CascadeType.ALL in #oneToMany? CascadeType.ALL will delete child entities when parent is deleted.
#OnDelete mainly used in child entities with #ManyToOne not otherwise.
Try with any option and check.
The error message is quite clear: There are foreign key references to the ServiceProviders you are trying to delete. Delete ServiceCenterDetails first:
delete from ServiceCenterDetails where serviceProvider.id = :providerId
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails
this exception tells that you should delete your ServiceCenterDetails associated with ServiceProviders first and then delete the ServiceProviders.
Related
I want to create an association between two entities Parent and Child with the constraint that Child ID correspond to a non unique property of Parent. Is it possible with Hibernate or shall I cope this without Hibernate ?
Here is Parent entity
public class Parent {
#column("parent_id")
private Integer parent_id
#column("identifiant")
private Integer identifiant
#column("version")
private Integer version
With a UNIQUE constraint on (identifiant, version)
and here is the Child Entity
public class Child{
#column("identifiant")
private Integer identifiant
#column("document1")
private byte[] document1
#column("document2")
private byte[] document2
with identifiant as primary key and also as foreign key on (Parent, identifiant)
Is it possible to manage this association with Hibernate and if so how, or shall I manage this association without hibernate and manage the Child Entity as a independant Entity ?
UPDATE
I found another issue. When I add a constraint of foreign key on (PARENT_TABLE, identifiant) like the following :
ALTER table PARENT_TABLE ADD CONSTRAINT cts_1 FOREIGN KEY (identifiant) REFERENCES CHILD_TABLE(identifiant);
it complaints that there are non existent row in CHILD_TABLE
I have 2 entities (User , Teacher) the User is the father ...
When I want to remove user by native query it give me this error ( Cannot delete or update a parent row: a foreign key constraint fail )
Though I have written:
#OneToOne(mappedBy = "user_id",fetch = FetchType.EAGER,
cascade = CascadeType.ALL , orphanRemoval = true )
at the Teacher reference in the user entity
but when I try to use JPA derived method deleteByEmail() .. it worked!
What is the reason?
Cascading doesn't work with queries.
It works when you change the state of the entities using the methods in the EntityManager or Hibernate ORM Session.
You can see a list of examples in the Hibernate ORM documentation:
5.15. Cascading entity state transitions.
I use following HQL query to delete a specific object in my database.
delete from com.ranking.Footballclub where id = 1
The problem I encounter when I do this, it breaks a foreign key.
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The DELETE
statement conflicted with the REFERENCE constraint
"FK_VKLC3OLNFZIT2FCYMMKDO2ERZ4". The conflict occurred in database
"sports", table "dbo.FOOTBALL_PLAYER", column 'CLUB_ID'
A sport teams has a slave of players. I could first delete all players before I delete the Footballclub. But a Footballclub has more than just players. It has for example a list of employees, transfers,... Their foreign keys will break as well.
For this case I'm looking for something in HQL to delete all slave fields in 1 statement.
you can set the ON DELETE CASCADE in the data base explicitly, or mark the required Child entity with the annotation #org.hibernate.annotations.OnDelete.
It will automatically adds the on delete to schema during the schema generation. like -
#OneToMany(fetch = FetchType.EAGER, mappedBy = "YOUR_PARENT",
cascade = CascadeType.REMOVE)
#org.hibernate.annotations.OnDelete(
action = #org.hibernate.annotations.OnDeleteAction.CASCADE)
private List<YOUR_CHILD> CHILDS;
You can only use #OneToMany(cascade=CascadeType.REMOVE) annotation at your Entity and delete it through entity manager. There is no option to do it with hql. Or use constraint in your DDL (foreign key delete cascade);
I am new to Hibernate. I have a OneToMany relationship with bidirectional mapping between Account and Transaction. I am not using #JoinColumn in either class and using #mappedBy in the non owning Account class. And everything is working fine. Using H2 in memory database, new join column is created in Transaction table. Then what is the use of #JoinColumn in OneToMany relationships? Is it for unidirectional mapping only? Below is the code. I also read for reference JPA JoinColumn vs mappedBy
public class Account {
#OneToMany( mappedBy="account", cascade=CascadeType.ALL)
List<Transaction> list= new ArrayList<Transaction>();
}
public class Transaction {
#ManyToOne
Account account;
}
Application class :
Account a = new Account("savings");
Transaction t1 = new Transaction("shoe purchase", 45);
t1.setAccount(a);
a.getList().add(t1);
accountRepository.save(a);
output:
Transaction table has an entry with foreign key which is account number in that one row in Account table. ACCOUNT_ID column in created in Transaction table.
There are no extra tables created.
Jpa works on the idea of configuration by convention. So, it will perform configuration on your behalf whenever it can. Think of the #Column annotation, you don't have to apply it on every entity attribute, you would need it only when you have to change something about the attributes.
It's the same with #JoinColumn, when you added #ManyToOne, Jpa already knows that you will need the join column and thus was added for you and the default naming convention for the foreign key was applied (attributename_primarykeyoftheothertype).
Use of
mappedBy
is instruct framework to enable bi-directional relationship. Because of #ManyToOne on Transaction class you Your Transaction Table will have foreign key referring to Account table primary key. By default, Hibernate generates the name of the foreign key column based on the name of the relationship mapping attribute and the name of the primary key attribute. In this example, Hibernate would use a column with the name account_id to store the foreign key to the Account entity.
#JoinColum
can be used If you would like override default foreign key name like #JoinColum(name="acc_id")
MappedBy intructs Hibernate that the key used for the association is on the other side of the association.Like in this case ACCOUNT_ID is being created on Account table.
That means that although you associate two tables together, only one table is having foreign key constraint to the other one.
MappedBylets you to still associate from the table not having foreign key constraint to the other table.
I have two persistable entities Obj1 and Obj2. Obj2 contains a reference to Obj like below. There is no reference (at code level - Java) to Obj2 in Obj1.
public class Obj2{
....
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE}, optional = true)
private Obj1 obj1;
I updated Ojbj 1 with #OneToMany as suggested:
public class Obj1{
....
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE,CascadeType.ALL},orphanRemoval = true)
private List<Obj2> obj2;
When I try to delete Obj1:
em.remove(obj1Instance)
It fails due to Foreigh Key constaint
00:35:23,109 WARN [com.arjuna.ats.arjuna] (http--127.0.0.1-8080-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff7f000101:-7f20c644:5369716f:26, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization#dcedf7 >: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`my_db`.`obj2`, CONSTRAINT `FKC4783505BB5D6339` FOREIGN KEY (`obj1_pk`) REFERENCES `obj1` (`pk`))
...
... 94 more
Caused by: org.hibernate.exception.ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`my_db`.`obj2`, CONSTRAINT `FKC4783505BB5D6339` FOREIGN KEY (`obj1_pk`) REFERENCES `obj1` (`pk`))
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`my_db`.`obj2`, CONSTRAINT `FKC4783505BB5D6339` FOREIGN KEY (`obj1_pk`) REFERENCES `obj1` (`pk`))
I had (wrongly it seems!) asumed that CascadeType.REMOVE would take care of this? How should I handle this delete?
/T
Either handle it manually or add a reverse relationship #OneToMany(orphanRemoval=true) in Obj1.
Thanks for the help guys... I managed to do it by (sort of ) combining both pieces of advice and I altered the Foreign Key so that it would CASCADE on DELETE.
When did you add optional = true? Is it before deploying the application or after? If it is after, MySQL wouldn't update the NotNull constraint on my_db.obj2, check if column obj1_pk is Nullable. If it is not, drop and add the constraint FKC4783505BB5D6339 so it can be Nullable.
Or you can simply drop these two tables and recreate them.