Skip to content

Commit 0c60266

Browse files
committed
Merge branch '7.0.x'
2 parents 99f6f1a + 0b5a9ea commit 0c60266

1 file changed

Lines changed: 34 additions & 6 deletions

File tree

spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,19 @@ protected Object invokeMethod(Method method, @Nullable Object[] args, Object tar
259259
Object result = method.invoke(target, args);
260260
if (result instanceof Query query) {
261261
if (newTarget) {
262+
InvocationHandler ih = new DeferredQueryInvocationHandler(query, target);
262263
Class<?>[] ifcs = cachedQueryInterfaces.computeIfAbsent(query.getClass(), key ->
263264
ClassUtils.getAllInterfacesForClass(key, this.proxyClassLoader));
264-
result = Proxy.newProxyInstance(this.proxyClassLoader, ifcs,
265-
new DeferredQueryInvocationHandler(query, target));
265+
try {
266+
result = Proxy.newProxyInstance(this.proxyClassLoader, ifcs, ih);
267+
}
268+
catch (IllegalArgumentException ex) {
269+
// Hibernate 8.0 NativeMutationOrSelectionQueryImpl multi-interface mismatch?
270+
// Fall back to single declared interface from method signature.
271+
Class<?>[] singleIfc = new Class<?>[] {method.getReturnType()};
272+
cachedQueryInterfaces.put(query.getClass(), singleIfc);
273+
result = Proxy.newProxyInstance(this.proxyClassLoader, singleIfc, ih);
274+
}
266275
close = false;
267276
}
268277
else {
@@ -523,7 +532,7 @@ private static class DeferredQueryInvocationHandler implements InvocationHandler
523532

524533
private @Nullable Map<@Nullable Object, @Nullable Object> outputParameters;
525534

526-
public DeferredQueryInvocationHandler(Query target, Object entityHandler) {
535+
public DeferredQueryInvocationHandler(Query target, @Nullable Object entityHandler) {
527536
this.target = target;
528537
this.entityHandler = entityHandler;
529538
}
@@ -551,7 +560,11 @@ else if (targetClass.isInstance(proxy)) {
551560
return proxy;
552561
}
553562
else {
554-
return this.target.unwrap(targetClass);
563+
Object retVal = this.target.unwrap(targetClass);
564+
if (retVal instanceof Query query && targetClass.isInterface()) {
565+
retVal = adaptQueryProxy(proxy, query, targetClass);
566+
}
567+
return retVal;
555568
}
556569
}
557570
case "getOutputParameterValue" -> {
@@ -572,14 +585,21 @@ else if (targetClass.isInstance(proxy)) {
572585
// Invoke method on actual Query object.
573586
try {
574587
Object retVal = method.invoke(this.target, args);
575-
if (method.getName().equals("registerStoredProcedureParameter") && args.length == 3 &&
588+
Class<?> returnType = method.getReturnType();
589+
if (retVal == this.target && returnType.isInstance(proxy)) {
590+
retVal = proxy;
591+
}
592+
else if (retVal instanceof Query query) {
593+
retVal = adaptQueryProxy(proxy, query, returnType);
594+
}
595+
else if (method.getName().equals("registerStoredProcedureParameter") && args.length == 3 &&
576596
(args[2] == ParameterMode.OUT || args[2] == ParameterMode.INOUT)) {
577597
if (this.outputParameters == null) {
578598
this.outputParameters = new LinkedHashMap<>();
579599
}
580600
this.outputParameters.put(args[0], null);
581601
}
582-
return (retVal == this.target ? proxy : retVal);
602+
return retVal;
583603
}
584604
catch (InvocationTargetException ex) {
585605
throw ex.getTargetException();
@@ -609,6 +629,14 @@ else if (targetClass.isInstance(proxy)) {
609629
}
610630
}
611631
}
632+
633+
private Object adaptQueryProxy(Object proxy, Query query, Class<?> expectedType) {
634+
InvocationHandler ih = this;
635+
if (query != this.target) {
636+
ih = new DeferredQueryInvocationHandler(query, this.entityHandler);
637+
}
638+
return Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class<?>[] {expectedType}, ih);
639+
}
612640
}
613641

614642
}

0 commit comments

Comments
 (0)