Get the specific column involved in a FK Exception - java

I faced with the follow message error (DataIntegrityViolationException) in an attempt of delete a specific record in my table:
Cannot delete or update a parent row: a foreign key constraint fails (company.table_parent, CONSTRAINT table_parent_ibfk_1 FOREIGN KEY (id_son) REFERENCES layout (id))
I already know the cause: I'm attempting to delete a record, however, it is being used in other table.
I'd like to know if exist a attribute that contains the table and the column involved in transaction attempt, order to I could treat properly the exception without check the error message content.

I don't know if this call is included in an outer wrapped transaction. as I see it you can:
(A) make the call and parse the error message. You will know the table/col of violation.
(B) query for existence in FK table (either parent or child) for columns suspected of subsequent violation before the update/delete call.
another way of looking at B is that you might be doing this against the parent table and it is a child table that is barking saying you are about to orphan me

Related

Does having a custom update query with WHERE clause gives more performance while updating in Spring Data JPA?

Let's say I have an entity called Car . Now the entity's primary key is not an auto generated Id. Lets say I need to update my car entity with a set of values.But the problem is I am having a requirement of ensuring the given Id is already existing in the database. Because I know in spring Data JPA we use the save() method to both save and update an existing entity.
Then in a case of inserting a new primary key for the save() method will lead to a save otherwise it will update that specific entity.So I always need to ensure during the update that the method will not create new entities for invalid ids.
So to overcome this issue I have seen many developers use a find() method call before the updation to ensure the given primary key is already existing.But you can see there will be an additional database hit to ensure that.
So to overcome this issue I thought of going with a custom update query.Then I can determine if the query is executed or not by declaring it's return type as int in the JPARepository. So according to my knowledge query will output 1 for success and 0 for a failed updation.
So what I need to know is, in the case of providing a not existing primary key for the method updateCar() can I always ensure that the update doesn't succeed because of that invalid primary key. I mean what happens if the update fails due to a different error?
The ultimate goal of this discussion is to avoid the check of the existence of the primary key before the updation. So if there any better approach please state it.
Ex:
#Modifying
#Query("UPDATE Car c SET c.status =:status WHERE c.id =:id")
int updateCar(#Param("status") String status, #Param("id") String id);
The int you get back from the update is the number of rows updated.
So what I need to know is, in the case of providing a not existing
primary key for the method updateCar() can I always ensure that the
update doesn't succeed because of that invalid primary key. I mean
what happens if the update fails due to a different error?
If the update fails for any other reason then you will get an Exception.
The problem with your solution is that you will have to write update statements for every use case.

Hibernate one to many mapping DataIntegrityViolationException

Hibernate One to many relation Below Process will work
insert into parent table
insert into child table
update the parent primary key in child table
Suppose if i am having a foreign key constrain in database for parent and child table
my step 2 will fail as with DataIntegrityViolationException.
What is the best solution
Heading
You should go with hibernate inheritance feature to achieve this

Multiple Consumers are Causing LockAcquisitionExecption somewhere in RestImpl class

My application is receiving JMSTextMessages from IBM Mq in bulk. For each message I am calling a REST API to process these messages. Somewhere when the API is processing these messages I am getting following exception logs, intermittently but very frequently:
java.lang.Exception: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement
2018-04-03 17:54:10.614 ERROR 5259 --- [.0-8083-exec-59] o.h.engine.jdbc.spi.SqlExceptionHelper : ORA-00060: deadlock detected while waiting for resource
It neither prints the table nor the query which it is trying to execute. To resolve this issue I tried pushing all Database processing code, in my REST API service code, inside a synchronized block, but still the same issue.Due to this issue every 2nd message fails to get processed.
Basis on a lot of material available online, it appears that each message received, triggers a new thread (at REST API service method end) and thus causing some deadlock kind of behavior in my app. Sadly, I am unable to figure out which piece of code exactly is causing this and we have a single thread when it comes to service application startup.
So now, I have decided to find out if I can introduce a delay before I start processing another message at the listener end. Again read a lot and everywhere I see XML property changes to handle this, but nothing comes handy if I want to do it via Spring Annotations. My app does not have any XML configs.
Here is my pseudo code:
#JmsListener(destination="queue_name")
public void receiveMessage(Object message){
myRestService.processMessage(message);
}
ServiceImpl code
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void processMessage(Object message){
Long id = getIdFromMessage(message);
X x = readFromDB(id);
updateDataInX(x, message);
savex(x);
}
I would also like to highlight that I have a parent-child relationship in the database. Where PRIMARY_KEY of parent table is PRIMARY_KEY (as well as FK) of child table and it is indexed as well. While I am updating values in above method (updateDataInX), some columns are being updated in child table row and some columns are being updated in parent table row (mapped to child row). The instance x is of CHILD class.
Apart from introducing a delay, how can I fix this? The producer is a separate application, and within a second they are sending multiple messages - which the consumer is clearly failing to process. This entirely is back-end update so I dont mind introducing a delay to have a fail-safe mechanism but I did not find any proper solution with spring annotations. Also if you can tell what exactly happens with threads at receiver side and rest API side. I am thoroughly confused reading about it since last 3 weeks.
My code also involved adding AUDIT logging data in one of the other CHILD tables, which was referring to a NON-PRIMARY key of the same PARENT table (Hierarchy of X).
While inserting a new row in CHILD table oracle was taking a full table lock which was resulting all subsequent inserts to fail with a deadlock issue.
Reason for taking a full table lock on CHILD table was that it had a foreign key column REFERENCE_NO which refers to the PARENT table.
When SQL statements from multiple sessions involve parent/child tables, a deadlock may occur with oracle default locking mechanism if the foreign key column in the child table is not indexed. Also Oracle takes a full table lock on the child table when primary key value is changed in the parent table.
In our case the PARENT.REFERENCE_NO is a non-primary key which is referred as foreign key in CHILD table. Every time we do a status update on PARENT table as mentioned in above pseudo code, hibernate fires update on REFERENCE_NO which results in locking the entire CHILD table, making it unavailable for AUDIT logging insertions.
So they Key Is : Oracle recommends to INDEX such foreign key columns due to which oracle does not take full table lock.

FK Constraint when adding using servlet

I have a code that adds values to two tables. However, what happens is im having a Foreign Key constraint in the reference table whenever I add. This is my code:
insert into `employee-personal-information`(lastName,firstName,gender,contactNo,age,address,email)
select applicantLastName,applicantFirstName,applicantGender,applicantContactNumber,applicantAge,applicantAddress,applicantEmail from applicant a
where a.applicantID=?;
But at the same time, I also execute this query when I press the add button:
insert into `employee-safeguard-information` (license) select a.applyingFor from applicant a where a.applicantID=?;
The problem with this code is that the data I am trying to insert in the employee personal information table is being updated but the code in the safeguard information does not update. I get an FK constraint. What can I do to solve this? Thanks!

Updating existing JPA child entities with FK in a single query

I have a parent/child one-to-many unidirectional relation.
Both the parent and the child POJOs use custom Insert-on-duplicate-update insert queries specified via #SQLInsert annotation.
Parent/child pair is inserted via cascading - everything works fine and the entity manager is closed.
Then I create a new entity manager and try to insert the same parent/child pair, but with updated values (same primary keys, but some of the other fields are changed).
The parent's Insert-on-duplicate-update works just fine and the values are updated.
In the child table however we end up with 2 entries, one with the old values and NULL parent_id foreign key, and one with the new values and correctly set FK.
I looked at the queries generated by Hibernate and found out the following:
The child row is inserted with the foreign key set to NULL
Then an update query is ran that sets the parent_id for the given child id
Another update is ran that sets the parent_id to NULL, I'm assuming for the child id of the first row
A third update query is ran that sets the parent_id
Is there a way for cascading insert to insert the child row and set the FK in the same query, thus eliminating the need for running a separate update query?
The question was answered as a part of a different question of mine:
JPA insert parent/child results in MySQLIntegrityConstraintViolationException
Basically, you have to set nullable = false in the #JoinColumn that specifies creates the parent/child relation.
There still seems to be an update query running for some reason but the complete record is being inserted with the insert statement.
The accepted answer did not solve my problem.
Adding updatable=false to the parent entity solved it. JPA does not execute the update query. However, I have no clue why that's the case and in fact, I don't think what I am doing is correct because it means I cannot update the child table later on if I have to.

Categories