You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello guys, I've got an issue with the PersistenceAnnotationBeanPostProcessor
when using multiple persistence units and inheritance. The problem is in
findPersistenceMetadata method which looks for persistence annotations in
registered beans.
The current implementation loops through declared fields and declared
methods of the actual class of the bean to detect eventual persistence
annotation and register a PersistenceElement for each.
And this process is repeated in a do ... while loop for each class in the
inheritance hierarchy of the bean's class.
Here is a simplified verion of the current algorithm:
The problem is that a PersistentElement is registered for each definition of a
field or method in the class hierarchy : the most specific definition is not
the only one registered.
One for @PersistenceContext with unitName "my-unit"
Then Spring injects the EntityManager based on the first element definition and
skip the second one which is the most specific!
There might be a good reason for iterating through each declared field/method
of each super class of the bean's class but I don't get why you do not simply
use the getMethods() and getFields() reflection methods which return the most
specific definition of the field/method with annotations and would avoid having
multiple injectedElements for persistence matadata?
This turned out to be a bug in the "most specific method" check that we had there anyway: Due to bad ordering, the most specific method only got checked for the @PersistenceUnit annotation but not for @PersistenceContext...
Fixed for 3.1 RC1 as well as 3.0.6 now. Thanks for raising it!
Nice catch on the parenthesis for pc != null && ClassUtils.getMostSpecificMethod! I'm sure that this will resolve a lot of problems for those using multiple persistence units in their projects.
Loïc Frering opened SPR-8594 and commented
Hello guys, I've got an issue with the PersistenceAnnotationBeanPostProcessor
when using multiple persistence units and inheritance. The problem is in
findPersistenceMetadata method which looks for persistence annotations in
registered beans.
The current implementation loops through declared fields and declared
methods of the actual class of the bean to detect eventual persistence
annotation and register a PersistenceElement for each.
And this process is repeated in a do ... while loop for each class in the
inheritance hierarchy of the bean's class.
Here is a simplified verion of the current algorithm:
Class<?> targetClass = clazz;do {
LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
for (Field field : targetClass.getDeclaredFields()) {
// .... currElements.add(new PersistenceElement(field, null));
}
for (Method method : targetClass.getDeclaredMethods()) {
// .... PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
currElements.add(new PersistenceElement(method, pd));
}
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}while (targetClass != null && targetClass != Object.class);
metadata = new InjectionMetadata(clazz, elements);
The problem is that a PersistentElement is registered for each definition of a
field or method in the class hierarchy : the most specific definition is not
the only one registered.
As a consequence having this:
public class GenericRepository {
public class UserRepository extends GenericRepository {
Would leed to 2 injected elements in metadata:
@PersistenceContext
without unitName@PersistenceContext
with unitName "my-unit"Then Spring injects the EntityManager based on the first element definition and
skip the second one which is the most specific!
There might be a good reason for iterating through each declared field/method
of each super class of the bean's class but I don't get why you do not simply
use the getMethods() and getFields() reflection methods which return the most
specific definition of the field/method with annotations and would avoid having
multiple injectedElements for persistence matadata?
Affects: 3.0.5
Referenced from: commits 65077d2, 49e61d2
The text was updated successfully, but these errors were encountered: