Getting Below error , why calling JPA method, frequently in Hibernate 6
org.springframework.dao.InvalidDataAccessApiUsageException: Illegal pop() with non-matching JdbcValuesSourceProcessingState
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:368)
We stumbled upon the same problem in our project where we were passing entity with OneToMany and ManyToOne relations with lazy loading to a method returning CompletableFuture. As a workaround we prepared DTO used for further operations outside of the method, passed it instead of the entity object and it worked like a charm
Related
This question already has answers here:
What are the differences between the different saving methods in Hibernate?
(10 answers)
Closed 7 years ago.
I was going through the JPA 2 specification and found two statements that sounds contradictory to me.
"If X is a preexisting managed entity, it is ignored by the persist operation." - Pg 76
"The EntityExistsException may thrown by the persistence provider when the persist operation is invoked and the entity already exists." - Pg 129
The statement 1 says something that sounds different from statement 2. So, my question is what is the difference between "preexisting managed entity" and "entity already exists"?
In version 2.1 of the spec, chapter 3.2.2, you can find this about the persist() operation:
If X is a preexisting managed entity, it is ignored by the persist operation. However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities are annotated with the cascade=PERSIST or cascade=ALL annotation element value or specified with the equivalent XML descriptor element.
If X is a removed entity, it becomes managed.
If X is a detached object, the EntityExistsException may be thrown when the persist operation is invoked, or the EntityExistsException or another PersistenceException may be thrown at flush or commit time
So, persist() will ignore the entity if it's a managed object. It can throw an exception (or throw it, or another one, later) if the entity is a detached object.
First case:
Foo foo = em.find(Foo.class, 1L);
em.persist(foo); // ignored
Second case:
Foo foo = new Foo();
foo.setId(1L);
em.persist(foo); // may throw an exception
I added the following method to one of my application entity.
public boolean isSame(TaskUser taskUser){
//some work
}
However I came across few threads like this one regarding hibernate errors for such kind of methods used without #Transient. But my application is running fine and also there is no column created in my DB table for the entity, so as a learner I want to ask what actually happens that save my app from hibernate error. Is that argument passed the reason?
This method does not define a property, so Hibernate is not interested in mapping a column for it.
The reason is that it is not a "getter". It does have the proper name ("isXXX" for a boolean), but it takes a parameter. Getters must be without parameters.
If it was a "real" getter, and you did not want it to result in a persistent property, you could use #Transient to suppress the automatic mapping.
I have the following question, which is not covered in Hibernate documentation. Or I just couldn't find the answer there. Googling doesn't give me details also.
If we use an Entity object as a parameter and bind it to an HQL using Query.setParameter, what happens next?
Does hibernate uses only an entity ID of a mapped parameter object to build the SQL 'where' query?
Or Hibernate uses some extra logic (maybe in some cases) which is not limited to ID only? For example, hibernate add additional fields in SQL which are not primary keys.
Is it dangerous to use detached Entity object as a parameter?
Thank you in advance!
In terms of the SQL it will simply compare using the ids. The entity you bind does not have to be managed within that session as the comment on your question suggests.
Essentially what happens is that Hibernate will attempt to resolve the entity type of the entity instance it is given. It will then use that type to bind the JDBC parameter value, which will write just the identifier. So the assumption here is that the entity instance can resolved to its "entity type". That is usually easy in most situations. Where it gets difficult is in the case of Hibernate-specific "entity name" features.
It seems that the Hibernate EntityManager find method behaves differently in the following two cases:
Case 1 - Entity does not exist in the database before transaction starts. Within transaction, find of the entity returns null.
Case 2 - Entity exists in DB before transaction. Within transaction, entity is remove'd, then a find of the same key throws EntityNotFoundException.
Is this expected behaviour? Do I need to do a flush before the find for it to behave the same?
It is unexpected that find method in EntityManager throws EntityNotFoundException when entity is not found. Documentation is quite clear:
Returns:
the found entity instance or null if the entity does not exist
This bug was reported in HHH-7861. It is fixed in 4.1.10, which is not yet released.
OK, answering the second part of my question, it seems that a flush between the remove and the find in case 2 makes it behave the same as case 1. That is, the find just returns null without throwing an exception (which is what we want, as the exception triggers a rollback).
Answer points will go to anyone who can tell me why the find should behave differently.
I have a JPA entity class (one of many) and I can run JPQL queries on it, returning that entity without any problem. However, when I attempt to run any named native query that selects all the fields on the underlying table, instead of mapping to the entity and returning a list of that entity type, I get a java.util.Vector of object arrays containing the result set. That is, the data is being returned, but not mapped to the entity. This is made worse by Java's fake generics, because the error manifests itself as a NumberFormatException in the EL parser.
My query calling code:
return em.createNamedQuery("ClinicDoctor.findUnchangedByClinicSystemId",
ClinicDoctor.class)
.setParameter(1, clinicSystemId)
.getResultList();
When I switch EclipseLink logging to FINE and run a JPQL query, the column names selected exactly match the column names I'm selecting in the native query.
Am I missing something? Is there some flaming hoop I should be jumping through to get the mapping to work?
Wouldn't you know it, right after asking this question I discovered that I just had to set the result-class attribute on the <named-native-query/> tag in my orm.xml and it worked.