Skip to content

Commit 293e296

Browse files
committed
Reflectively invoke getIdentifier method (for compatibility with Hibernate 6)
Closes gh-28855
1 parent 38c9e7f commit 293e296

8 files changed

+51
-22
lines changed

spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -82,7 +82,7 @@ public ObjectOptimisticLockingFailureException(
8282
* @param cause the source exception
8383
*/
8484
public ObjectOptimisticLockingFailureException(
85-
Class<?> persistentClass, Object identifier, String msg, @Nullable Throwable cause) {
85+
Class<?> persistentClass, @Nullable Object identifier, String msg, @Nullable Throwable cause) {
8686

8787
super(msg, cause);
8888
this.persistentClass = persistentClass;
@@ -123,7 +123,7 @@ public ObjectOptimisticLockingFailureException(
123123
* @param cause the source exception
124124
*/
125125
public ObjectOptimisticLockingFailureException(
126-
String persistentClassName, Object identifier, String msg, @Nullable Throwable cause) {
126+
String persistentClassName, @Nullable Object identifier, String msg, @Nullable Throwable cause) {
127127

128128
super(msg, cause);
129129
this.persistentClass = persistentClassName;

spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ public ObjectRetrievalFailureException(Class<?> persistentClass, Object identifi
6969
* @param cause the source exception
7070
*/
7171
public ObjectRetrievalFailureException(
72-
Class<?> persistentClass, Object identifier, String msg, @Nullable Throwable cause) {
72+
Class<?> persistentClass, @Nullable Object identifier, String msg, @Nullable Throwable cause) {
7373

7474
super(msg, cause);
7575
this.persistentClass = persistentClass;
@@ -97,7 +97,7 @@ public ObjectRetrievalFailureException(String persistentClassName, Object identi
9797
* @param cause the source exception
9898
*/
9999
public ObjectRetrievalFailureException(
100-
String persistentClassName, Object identifier, String msg, @Nullable Throwable cause) {
100+
String persistentClassName, @Nullable Object identifier, String msg, @Nullable Throwable cause) {
101101

102102
super(msg, cause);
103103
this.persistentClass = persistentClassName;

spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,13 @@
1616

1717
package org.springframework.orm.hibernate5;
1818

19+
import org.hibernate.HibernateException;
1920
import org.hibernate.UnresolvableObjectException;
2021
import org.hibernate.WrongClassException;
2122

23+
import org.springframework.lang.Nullable;
2224
import org.springframework.orm.ObjectRetrievalFailureException;
25+
import org.springframework.util.ReflectionUtils;
2326

2427
/**
2528
* Hibernate-specific subclass of ObjectRetrievalFailureException.
@@ -33,11 +36,24 @@
3336
public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException {
3437

3538
public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) {
36-
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
39+
super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex);
3740
}
3841

3942
public HibernateObjectRetrievalFailureException(WrongClassException ex) {
40-
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
43+
super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex);
44+
}
45+
46+
47+
@Nullable
48+
static Object getIdentifier(HibernateException hibEx) {
49+
try {
50+
// getIdentifier declares Serializable return value on 5.x but Object on 6.x
51+
// -> not binary compatible, let's invoke it reflectively for the time being
52+
return ReflectionUtils.invokeMethod(hibEx.getClass().getMethod("getIdentifier"), hibEx);
53+
}
54+
catch (NoSuchMethodException ex) {
55+
return null;
56+
}
4157
}
4258

4359
}

spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
3535
public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
3636

3737
public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) {
38-
super(ex.getEntityName(), ex.getIdentifier(), ex);
38+
super(ex.getEntityName(), HibernateObjectRetrievalFailureException.getIdentifier(ex), ex.getMessage(), ex);
3939
}
4040

4141
public HibernateOptimisticLockingFailureException(StaleStateException ex) {

spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@
5757
* way to set up a shared Hibernate SessionFactory in a Spring application context; the
5858
* SessionFactory can then be passed to data access objects via dependency injection.
5959
*
60-
* <p>Compatible with Hibernate 5.5/5.6, as of Spring 6.0.
60+
* <p>Compatible with Hibernate ORM 5.5/5.6, as of Spring Framework 6.0.
6161
* This Hibernate-specific {@code LocalSessionFactoryBean} can be an immediate alternative
6262
* to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for
6363
* common JPA purposes: The Hibernate {@code SessionFactory} will natively expose the JPA

spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@
7878
* Typically combined with {@link HibernateTransactionManager} for declarative
7979
* transactions against the {@code SessionFactory} and its JDBC {@code DataSource}.
8080
*
81-
* <p>Compatible with Hibernate 5.5/5.6, as of Spring 6.0.
81+
* <p>Compatible with Hibernate ORM 5.5/5.6, as of Spring Framework 6.0.
8282
* This Hibernate-specific factory builder can also be a convenient way to set up
8383
* a JPA {@code EntityManagerFactory} since the Hibernate {@code SessionFactory}
8484
* natively exposes the JPA {@code EntityManagerFactory} interface as well now.

spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@
7070
import org.springframework.transaction.TransactionDefinition;
7171
import org.springframework.transaction.TransactionException;
7272
import org.springframework.transaction.support.ResourceTransactionDefinition;
73+
import org.springframework.util.ReflectionUtils;
7374

7475
/**
75-
* {@link org.springframework.orm.jpa.JpaDialect} implementation for
76-
* Hibernate EntityManager.
76+
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate.
77+
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1.
7778
*
7879
* @author Juergen Hoeller
7980
* @author Costin Leau
@@ -295,13 +296,13 @@ protected DataAccessException convertHibernateAccessException(HibernateException
295296
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
296297
}
297298
if (ex instanceof UnresolvableObjectException hibEx) {
298-
return new ObjectRetrievalFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex.getMessage(), ex);
299+
return new ObjectRetrievalFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex);
299300
}
300301
if (ex instanceof WrongClassException hibEx) {
301-
return new ObjectRetrievalFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex.getMessage(), ex);
302+
return new ObjectRetrievalFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex);
302303
}
303304
if (ex instanceof StaleObjectStateException hibEx) {
304-
return new ObjectOptimisticLockingFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex);
305+
return new ObjectOptimisticLockingFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex);
305306
}
306307
if (ex instanceof StaleStateException) {
307308
return new ObjectOptimisticLockingFailureException(ex.getMessage(), ex);
@@ -324,6 +325,18 @@ protected SessionImplementor getSession(EntityManager entityManager) {
324325
return entityManager.unwrap(SessionImplementor.class);
325326
}
326327

328+
@Nullable
329+
protected Object getIdentifier(HibernateException hibEx) {
330+
try {
331+
// getIdentifier declares Serializable return value on 5.x but Object on 6.x
332+
// -> not binary compatible, let's invoke it reflectively for the time being
333+
return ReflectionUtils.invokeMethod(hibEx.getClass().getMethod("getIdentifier"), hibEx);
334+
}
335+
catch (NoSuchMethodException ex) {
336+
return null;
337+
}
338+
}
339+
327340

328341
private static class SessionTransactionData {
329342

spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
import org.springframework.lang.Nullable;
4444

4545
/**
46-
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate
47-
* EntityManager.
46+
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
47+
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1.
4848
*
4949
* <p>Exposes Hibernate's persistence provider and Hibernate's Session as extended
5050
* EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common

0 commit comments

Comments
 (0)