diff --git a/spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java b/spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java index ea6c875b3f8..db7b206225c 100644 --- a/spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java +++ b/spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,7 +82,7 @@ public class ObjectOptimisticLockingFailureException extends OptimisticLockingFa * @param cause the source exception */ public ObjectOptimisticLockingFailureException( - Class> persistentClass, Object identifier, String msg, @Nullable Throwable cause) { + Class> persistentClass, @Nullable Object identifier, String msg, @Nullable Throwable cause) { super(msg, cause); this.persistentClass = persistentClass; @@ -123,7 +123,7 @@ public class ObjectOptimisticLockingFailureException extends OptimisticLockingFa * @param cause the source exception */ public ObjectOptimisticLockingFailureException( - String persistentClassName, Object identifier, String msg, @Nullable Throwable cause) { + String persistentClassName, @Nullable Object identifier, String msg, @Nullable Throwable cause) { super(msg, cause); this.persistentClass = persistentClassName; diff --git a/spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java b/spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java index 6414d9649cf..31e3239b1cd 100644 --- a/spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java +++ b/spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,7 +69,7 @@ public class ObjectRetrievalFailureException extends DataRetrievalFailureExcepti * @param cause the source exception */ public ObjectRetrievalFailureException( - Class> persistentClass, Object identifier, String msg, @Nullable Throwable cause) { + Class> persistentClass, @Nullable Object identifier, String msg, @Nullable Throwable cause) { super(msg, cause); this.persistentClass = persistentClass; @@ -97,7 +97,7 @@ public class ObjectRetrievalFailureException extends DataRetrievalFailureExcepti * @param cause the source exception */ public ObjectRetrievalFailureException( - String persistentClassName, Object identifier, String msg, @Nullable Throwable cause) { + String persistentClassName, @Nullable Object identifier, String msg, @Nullable Throwable cause) { super(msg, cause); this.persistentClass = persistentClassName; diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java index 3f1d4b4bc83..150ae55c6d1 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,13 @@ package org.springframework.orm.hibernate5; +import org.hibernate.HibernateException; import org.hibernate.UnresolvableObjectException; import org.hibernate.WrongClassException; +import org.springframework.lang.Nullable; import org.springframework.orm.ObjectRetrievalFailureException; +import org.springframework.util.ReflectionUtils; /** * Hibernate-specific subclass of ObjectRetrievalFailureException. @@ -33,11 +36,24 @@ import org.springframework.orm.ObjectRetrievalFailureException; public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException { public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) { - super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex); + super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex); } public HibernateObjectRetrievalFailureException(WrongClassException ex) { - super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex); + super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex); + } + + + @Nullable + static Object getIdentifier(HibernateException hibEx) { + try { + // getIdentifier declares Serializable return value on 5.x but Object on 6.x + // -> not binary compatible, let's invoke it reflectively for the time being + return ReflectionUtils.invokeMethod(hibEx.getClass().getMethod("getIdentifier"), hibEx); + } + catch (NoSuchMethodException ex) { + return null; + } } } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java index 8b069ed01bb..0246df5a281 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import org.springframework.orm.ObjectOptimisticLockingFailureException; public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException { public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) { - super(ex.getEntityName(), ex.getIdentifier(), ex); + super(ex.getEntityName(), HibernateObjectRetrievalFailureException.getIdentifier(ex), ex.getMessage(), ex); } public HibernateOptimisticLockingFailureException(StaleStateException ex) { diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java index 7dc063b2a52..fdf6a98b422 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ import org.springframework.lang.Nullable; * way to set up a shared Hibernate SessionFactory in a Spring application context; the * SessionFactory can then be passed to data access objects via dependency injection. * - *
Compatible with Hibernate 5.5/5.6, as of Spring 6.0. + *
Compatible with Hibernate ORM 5.5/5.6, as of Spring Framework 6.0. * This Hibernate-specific {@code LocalSessionFactoryBean} can be an immediate alternative * to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for * common JPA purposes: The Hibernate {@code SessionFactory} will natively expose the JPA diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java index e2346f1088b..92385166f81 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,7 +78,7 @@ import org.springframework.util.ClassUtils; * Typically combined with {@link HibernateTransactionManager} for declarative * transactions against the {@code SessionFactory} and its JDBC {@code DataSource}. * - *
Compatible with Hibernate 5.5/5.6, as of Spring 6.0. + *
Compatible with Hibernate ORM 5.5/5.6, as of Spring Framework 6.0. * This Hibernate-specific factory builder can also be a convenient way to set up * a JPA {@code EntityManagerFactory} since the Hibernate {@code SessionFactory} * natively exposes the JPA {@code EntityManagerFactory} interface as well now. diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java index 716a6c1cf0f..a29611d6645 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java @@ -70,10 +70,11 @@ import org.springframework.transaction.InvalidIsolationLevelException; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; import org.springframework.transaction.support.ResourceTransactionDefinition; +import org.springframework.util.ReflectionUtils; /** - * {@link org.springframework.orm.jpa.JpaDialect} implementation for - * Hibernate EntityManager. + * {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate. + * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1. * * @author Juergen Hoeller * @author Costin Leau @@ -295,13 +296,13 @@ public class HibernateJpaDialect extends DefaultJpaDialect { return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); } if (ex instanceof UnresolvableObjectException hibEx) { - return new ObjectRetrievalFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex.getMessage(), ex); + return new ObjectRetrievalFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex); } if (ex instanceof WrongClassException hibEx) { - return new ObjectRetrievalFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex.getMessage(), ex); + return new ObjectRetrievalFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex); } if (ex instanceof StaleObjectStateException hibEx) { - return new ObjectOptimisticLockingFailureException(hibEx.getEntityName(), hibEx.getIdentifier(), ex); + return new ObjectOptimisticLockingFailureException(hibEx.getEntityName(), getIdentifier(hibEx), ex.getMessage(), ex); } if (ex instanceof StaleStateException) { return new ObjectOptimisticLockingFailureException(ex.getMessage(), ex); @@ -324,6 +325,18 @@ public class HibernateJpaDialect extends DefaultJpaDialect { return entityManager.unwrap(SessionImplementor.class); } + @Nullable + protected Object getIdentifier(HibernateException hibEx) { + try { + // getIdentifier declares Serializable return value on 5.x but Object on 6.x + // -> not binary compatible, let's invoke it reflectively for the time being + return ReflectionUtils.invokeMethod(hibEx.getClass().getMethod("getIdentifier"), hibEx); + } + catch (NoSuchMethodException ex) { + return null; + } + } + private static class SessionTransactionData { diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java index 1af984c6fde..6bc9a75a77e 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java @@ -43,8 +43,8 @@ import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.springframework.lang.Nullable; /** - * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate - * EntityManager. + * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate. + * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1. * *
Exposes Hibernate's persistence provider and Hibernate's Session as extended * EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common