Saturday, May 16, 2020

JPA entity removal fails silently


>PROBLEM


The JPA remove command was silently ignored.
There was no delete statement on server's output even though the show_sql was enabled:
 
<property name="hibernate.show_sql" value="true"></property>
 
 
The issue was around an OneToMany relation where:
todo 1 --- * todoitem
 

Attempt to delete an instance on any side fails silently, without having the respective "delete" command on the server's output and no exception message of any type.

 

>SOLUTION

 
First, I switched the many side's code suggested by the Wildfly18/JBoss documentation in its examples from:
 
//    @Override
//    public void delete(Todoitem todoitem) {
//        if (todoitem == null) {
//            return;
//        }
//        if (!emPg.contains(todoitem)) {
//            todoitem = emPg.merge(todoitem);
//        }
//        emPg.remove(todoitem);
//        emPg.flush();
//        emPg.clear();
//    }
    

To an equivalent form:
 
    @Override
    public void delete(Todoitem todoitem) {
        if (todoitem == null) {
            return;
        }
        Todoitem ti = emPg.find(Todoitem.class, todoitem.getId());
        if(ti == null) {
            return;
        }
        emPg.remove(ti);
        emPg.flush();
        emPg.clear();
    }
 

Unfortunately, I got the same result - removal silently ignored.
 

Then, I suspected of the database, since hibernate handles its own keys. I had done many tests during implementation...
To be sure about the consistency issues, I've decided to empty the database deleting the content of both sides of the relation.
Then I created new entity instances and relations using the application's resources (no SQL command) since everything was working well except for entity removal.
After, I checked the database relations using SQL command to make sure everything was fine, and it was.
 
Next, I tried a new test again but this time it was successful.

Then I reverted the code, uncommenting the commented code and vice-versa and tested again.
The test failed again, returning same result — silently ignoring remove.

I set back the code to the previous condition testing again to confirm results.
The confirmations was successful, confirming suspicion of two issues, database and code implementation.
 
Since good news, I repeated the same to the "One" side (code below - the commented code is the initial one inherited from Wildfly 18 documentation, as above mentioned). 
 
From:
//    @Override
//    public void delete(Todo todo) {
//        if(todo == null) {
//            return;
//        }
//        if (!emPg.contains(todo)) {
//            todo = emPg.merge(todo);
//        }
//        //todoitemDao.deleteAll(todo);
//        emPg.remove(todo);
//        emPg.flush();
//    }
 
 
To:
    
    @Override
    public void delete(Todo todo) {
        if (todo == null) {
            return;
        }
        Todo t = emPg.find(Todo.class, todo.getId());
        if(t == null) {
            return;
        }
        emPg.remove(t);
        emPg.flush();
        emPg.clear();
    }
 

 
Issue solved. Success.
 

IMPORTANT NOTE:
 
Check the removal tests by using the SQL statements straight on the database.
Sometimes the instance seems not being removed due to cache issue or code implementation fault, requiring to be treated apart.


>ENV


- JSF
- Wildfly 18 (JPA default implementation - Hibernate)
- PostgreSQL 10


>NOTE

Published also on Stackoverflow

No comments:

Post a Comment

eclipse: java: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" or Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder

  >PROBLEM Using Eclipse, you try to run a simple logging test using "org.slf4j.Logger" like the sample below: package Test; im...