diff --git a/documentation/src/main/asciidoc/userguide/chapters/pc/PersistenceContext.adoc b/documentation/src/main/asciidoc/userguide/chapters/pc/PersistenceContext.adoc index c7a4aaa620..67e9358697 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/pc/PersistenceContext.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/pc/PersistenceContext.adoc @@ -886,16 +886,7 @@ See the discussion of non-identifier <> section as well. +however, Jakarta Persistence prohibits this practice and specifies that an `IllegalArgumentException` should be thrown instead. This is the default behaviour from version 7.0 onwards. ==== [[pc-refresh-gotchas]] diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java index 68f38f5126..9d0c7273f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java @@ -426,11 +426,6 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement return this; } - @Override - public void disableRefreshDetachedEntity() { - this.optionsBuilder.disableRefreshDetachedEntity(); - } - @Override public void disableJtaTransactionAccess() { this.optionsBuilder.disableJtaTransactionAccess(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java index f8c9fe7c60..ea6f1e21a7 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java @@ -75,7 +75,6 @@ import org.hibernate.type.format.jaxb.JaxbXmlFormatMapper; import jakarta.persistence.criteria.Nulls; import static org.hibernate.cfg.AvailableSettings.ALLOW_JTA_TRANSACTION_ACCESS; -import static org.hibernate.cfg.AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY; import static org.hibernate.cfg.AvailableSettings.ALLOW_UPDATE_OUTSIDE_TRANSACTION; import static org.hibernate.cfg.AvailableSettings.AUTO_CLOSE_SESSION; import static org.hibernate.cfg.AvailableSettings.AUTO_EVICT_COLLECTION_CACHE; @@ -176,7 +175,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { private boolean jtaTransactionAccessEnabled; private boolean allowOutOfTransactionUpdateOperations; private boolean releaseResourcesOnCloseEnabled; - private boolean allowRefreshDetachedEntity; // (JTA) transaction handling private boolean jtaTrackByThread; @@ -335,12 +333,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { true ); - this.allowRefreshDetachedEntity = configurationService.getSetting( - ALLOW_REFRESH_DETACHED_ENTITY, - BOOLEAN, - false - ); - this.flushBeforeCompletionEnabled = configurationService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true ); this.autoCloseSessionEnabled = configurationService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false ); @@ -906,11 +898,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { return jtaTransactionAccessEnabled; } - @Override - public boolean isAllowRefreshDetachedEntity() { - return allowRefreshDetachedEntity; - } - @Override public boolean isAllowOutOfTransactionUpdateOperations() { return allowOutOfTransactionUpdateOperations; @@ -1624,10 +1611,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { this.collectionsInDefaultFetchGroupEnabled = enabled; } - public void disableRefreshDetachedEntity() { - this.allowRefreshDetachedEntity = false; - } - public void disableJtaTransactionAccess() { this.jtaTransactionAccessEnabled = false; } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java index 496a0f9083..47e1bce732 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java @@ -37,6 +37,8 @@ import org.hibernate.type.format.FormatMapper; import jakarta.persistence.criteria.Nulls; +import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; + /** * Convenience base class for custom implementations of {@link SessionFactoryOptions} * using delegation. @@ -77,8 +79,13 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp return delegate.isJtaTransactionAccessEnabled(); } + /** + * @deprecated with no replacement. + */ + @Deprecated(since = "7.0", forRemoval = true) @Override public boolean isAllowRefreshDetachedEntity() { + DEPRECATION_LOGGER.deprecatedRefreshLockDetachedEntity(); return delegate.isAllowRefreshDetachedEntity(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderImplementor.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderImplementor.java index d5793e8ed2..1c280fac11 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderImplementor.java @@ -5,6 +5,7 @@ package org.hibernate.boot.spi; import org.hibernate.boot.SessionFactoryBuilder; +import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; /** * Additional SPI contract for {@link SessionFactoryBuilder}, mainly intended for @@ -21,10 +22,11 @@ public interface SessionFactoryBuilderImplementor extends SessionFactoryBuilder void disableJtaTransactionAccess(); /** - * Called if {@link org.hibernate.cfg.AvailableSettings#ALLOW_REFRESH_DETACHED_ENTITY} - * is not enabled. + * @deprecated with no replacement. */ + @Deprecated(since = "7.0", forRemoval = true) default void disableRefreshDetachedEntity() { + DEPRECATION_LOGGER.deprecatedRefreshLockDetachedEntity(); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java index 645f5ee183..7967c85b1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java @@ -34,6 +34,8 @@ import org.hibernate.type.format.FormatMapper; import jakarta.persistence.criteria.Nulls; +import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; + /** * Aggregator of special options used to build the {@link org.hibernate.SessionFactory}. * @@ -76,7 +78,12 @@ public interface SessionFactoryOptions extends QueryEngineOptions { boolean isJtaTransactionAccessEnabled(); + /** + * @deprecated with no replacement. + */ + @Deprecated(since = "7.0", forRemoval = true) default boolean isAllowRefreshDetachedEntity() { + DEPRECATION_LOGGER.deprecatedRefreshLockDetachedEntity(); return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 025898ee8b..7ade5077bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -120,24 +120,6 @@ public interface AvailableSettings */ String DELAY_ENTITY_LOADER_CREATIONS = "hibernate.loader.delay_entity_loader_creations"; - /** - * When enabled, allows calls to {@link jakarta.persistence.EntityManager#refresh(Object)} - * and {@link org.hibernate.Session#refresh(Object)} on a detached entity instance. - *

- * Values are {@code true}, which allows refreshing a detached instance and {@code false}, - * which does not. When refreshing is disallowed, an {@link IllegalArgumentException} - * is thrown. - *

- * The default behavior is to allow refreshing a detached instance unless Hibernate - * is bootstrapped via JPA. - * - * @deprecated Will be removed with no replacement from ORM version 7 onwards - * - * @since 5.2 - */ - @Deprecated(since="6.6", forRemoval = true) - String ALLOW_REFRESH_DETACHED_ENTITY = "hibernate.allow_refresh_detached_entity"; - /** * Specifies how Hibernate should behave when multiple representations of the same * persistent entity instance, that is, multiple detached objects with the same diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 23515083d9..d49b75512a 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -1245,10 +1245,8 @@ public class SessionImpl } private void checkEntityManaged(String entityName, Object entity) { - if ( !getSessionFactory().getSessionFactoryOptions().isAllowRefreshDetachedEntity() ) { - if ( !managed( entityName, entity ) ) { - throw new IllegalArgumentException( "Given entity is not associated with the persistence context" ); - } + if ( !managed( entityName, entity ) ) { + throw new IllegalArgumentException( "Given entity is not associated with the persistence context" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java index a89b2f0d93..0cfbdcd45f 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java @@ -187,4 +187,11 @@ public interface DeprecationLogger extends BasicLogger { value = "Encountered use of deprecated annotation [%s] at %s." ) void deprecatedAnnotation(Class annotationType, String locationDescription); + + @LogMessage(level = WARN) + @Message( + id = 90000034, + value = "Refreshing/locking detached entities is no longer allowed." + ) + void deprecatedRefreshLockDetachedEntity(); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index 26e531ef84..22e53e68eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -1479,7 +1479,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // builder.applyInterceptor( sessionFactoryInterceptor ); // } handleAllowJtaTransactionAccess( builder ); - handleAllowDetachedEntity( builder ); addConfiguredSessionFactoryObserver( builder ); builder.addSessionFactoryObservers( ServiceRegistryCloser.INSTANCE ); builder.applyEntityNotFoundDelegate( JpaEntityNotFoundDelegate.INSTANCE ); @@ -1500,16 +1499,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } - // will use user override value or default to false if not supplied to follow JPA spec - private void handleAllowDetachedEntity(SessionFactoryBuilder builder) { - final boolean allowRefreshDetachedEntity = - readBooleanConfigurationValue( AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY ); - if ( !allowRefreshDetachedEntity - && builder instanceof SessionFactoryBuilderImplementor implementor ) { - implementor.disableRefreshDetachedEntity(); - } - } - // will use user override value or default to false if not supplied to follow JPA spec private void handleAllowJtaTransactionAccess(SessionFactoryBuilder builder) { final boolean jtaTransactionAccessEnabled = diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTest2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTest2.java index 2bfcff5dcd..d4ea2d451f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTest2.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTest2.java @@ -5,15 +5,13 @@ package org.hibernate.orm.test.bytecode.enhancement.lazy.HHH_10708; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -34,7 +32,6 @@ import java.util.Set; ) @SessionFactory @BytecodeEnhanced -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class UnexpectedDeleteTest2 { private Bar myBar; @@ -59,8 +56,10 @@ public class UnexpectedDeleteTest2 { @Test public void test(SessionFactoryScope scope) { scope.inTransaction( s -> { - s.refresh( myBar ); - assertFalse( myBar.foos.isEmpty() ); + assertThrows(IllegalArgumentException.class, + () -> s.refresh( myBar ), + "Given entity is not associated with the persistence context" + ); // The issue is that currently, for some unknown reason, foos are deleted on flush } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/backref/BackrefCompositeMapKeyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/backref/BackrefCompositeMapKeyTest.java index 8410aaeba2..f6d0275da3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/backref/BackrefCompositeMapKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/backref/BackrefCompositeMapKeyTest.java @@ -6,7 +6,6 @@ package org.hibernate.orm.test.bytecode.enhancement.lazy.backref; import org.hibernate.Hibernate; import org.hibernate.LockMode; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.orm.test.bytecode.enhancement.lazy.NoDirtyCheckingContext; import org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.DirtyCheckEnhancementContext; @@ -17,14 +16,13 @@ import org.hibernate.orm.test.collection.backref.map.compkey.Product; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -42,7 +40,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @SessionFactory @BytecodeEnhanced @CustomEnhancementContext({ NoDirtyCheckingContext.class, DirtyCheckEnhancementContext.class }) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class BackrefCompositeMapKeyTest { @Test @@ -123,7 +120,7 @@ public class BackrefCompositeMapKeyTest { } @Test - public void testOrphanDeleteAfterLock(SessionFactoryScope scope) { + public void testCannotLockDetachedEntity(SessionFactoryScope scope) { Product prod = new Product( "Widget" ); MapKey mapKey = new MapKey( "Top" ); scope.inTransaction( @@ -139,14 +136,16 @@ public class BackrefCompositeMapKeyTest { scope.inTransaction( session -> { - session.lock( prod, LockMode.READ ); - prod.getParts().remove( mapKey ); + assertThrows(IllegalArgumentException.class, + () -> session.lock( prod, LockMode.READ ), + "Given entity is not associated with the persistence context" + ); } ); scope.inTransaction( session -> { - assertNull( session.get( Part.class, "Widge" ) ); + assertNotNull( session.get( Part.class, "Widge" ) ); assertNotNull( session.get( Part.class, "Get" ) ); session.remove( session.get( Product.class, "Widget" ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OrphanTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OrphanTest.java index 4ee60a41c6..582741255d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OrphanTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OrphanTest.java @@ -7,7 +7,6 @@ package org.hibernate.orm.test.bytecode.enhancement.orphan; import org.hibernate.Hibernate; import org.hibernate.LockMode; import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.orm.test.orphan.Part; import org.hibernate.orm.test.orphan.Product; @@ -17,15 +16,14 @@ import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -42,7 +40,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; EnhancerTestContext.class, // supports laziness and dirty-checking DefaultEnhancementContext.class }) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class OrphanTest { @AfterEach @@ -152,7 +149,7 @@ public class OrphanTest { @Test @SuppressWarnings("unchecked") - public void testOrphanDeleteAfterLock(SessionFactoryScope scope) { + public void testCannotLockDetachedEntity(SessionFactoryScope scope) { Product prod = new Product(); Part part = new Part(); scope.inTransaction( @@ -172,14 +169,16 @@ public class OrphanTest { scope.inTransaction( session -> { - session.lock( prod, LockMode.READ ); - prod.getParts().remove( part ); + assertThrows(IllegalArgumentException.class, + () -> session.lock( prod, LockMode.READ ), + "Given entity is not associated with the persistence context" + ); } ); scope.inTransaction( session -> { - assertNull( session.get( Part.class, "Widge" ) ); + assertNotNull( session.get( Part.class, "Widge" ) ); assertNotNull( session.get( Part.class, "Get" ) ); session.remove( session.get( Product.class, "Widget" ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/cascade/RefreshTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/cascade/RefreshTest.java index 3155e942b5..0e54b6e3bc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/cascade/RefreshTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/cascade/RefreshTest.java @@ -19,18 +19,17 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; + import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Implementation of RefreshTest. @@ -44,7 +43,6 @@ import static org.junit.Assert.assertEquals; } ) @SessionFactory -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class RefreshTest { private JobBatch batch; @@ -67,11 +65,14 @@ public class RefreshTest { } @Test - void testRefreshCascade(SessionFactoryScope scope) { + void testCannotRefreshCascadeDetachedEntity(SessionFactoryScope scope) { scope.inTransaction( session -> { - session.refresh( batch ); - batch.jobs.forEach( job -> assertEquals( "Jobs not refreshed!", 1, job.status ) ); + assertThrows(IllegalArgumentException.class, + () -> session.refresh( batch ), + "Given entity is not associated with the persistence context" + ); + batch.jobs.forEach( job -> assertEquals( 0, job.status ) ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java index 484f192ac1..ee03aee9b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/backref/map/compkey/BackrefCompositeMapKeyTest.java @@ -6,18 +6,16 @@ package org.hibernate.orm.test.collection.backref.map.compkey; import org.hibernate.Hibernate; import org.hibernate.LockMode; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -33,7 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; ) ) @SessionFactory -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class BackrefCompositeMapKeyTest { @Test @@ -114,7 +111,7 @@ public class BackrefCompositeMapKeyTest { } @Test - public void testOrphanDeleteAfterLock(SessionFactoryScope scope) { + public void testCannotLockDetachedEntity(SessionFactoryScope scope) { Product prod = new Product( "Widget" ); MapKey mapKey = new MapKey( "Top" ); scope.inTransaction( @@ -130,14 +127,16 @@ public class BackrefCompositeMapKeyTest { scope.inTransaction( session -> { - session.lock( prod, LockMode.READ ); - prod.getParts().remove( mapKey ); + assertThrows(IllegalArgumentException.class, + () -> session.lock( prod, LockMode.READ ), + "Given entity is not associated with the persistence context" + ); } ); scope.inTransaction( session -> { - assertNull( session.get( Part.class, "Widge" ) ); + assertNotNull( session.get( Part.class, "Widge" ) ); assertNotNull( session.get( Part.class, "Get" ) ); session.remove( session.get( Product.class, "Widget" ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/ImmutableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/ImmutableTest.java index beb9417a89..c58fa326a9 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/ImmutableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/ImmutableTest.java @@ -63,7 +63,6 @@ public class ImmutableTest extends BaseSessionFactoryFunctionalTest { protected void applySettings(StandardServiceRegistryBuilder builer) { builer.applySetting( Environment.GENERATE_STATISTICS, "true" ); builer.applySetting( Environment.STATEMENT_BATCH_SIZE, "0" ); - builer.applySetting( Environment.ALLOW_REFRESH_DETACHED_ENTITY, "true" ); } @Override @@ -365,18 +364,9 @@ public class ImmutableTest extends BaseSessionFactoryFunctionalTest { inTransaction( s -> { - // refresh detached - s.refresh( contract ); - assertTrue( s.isReadOnly( contract ) ); - assertEquals( "gavin", contract.getCustomerName() ); - assertEquals( 2, contract.getVariations().size() ); - Iterator it = contract.getVariations().iterator(); - ContractVariation cv1 = it.next(); - assertEquals( "expensive", cv1.getText() ); - ContractVariation cv2 = it.next(); - assertEquals( "more expensive", cv2.getText() ); - assertTrue( s.isReadOnly( cv1 ) ); - assertTrue( s.isReadOnly( cv2 ) ); + Contract c = s.get(Contract.class, contract.getId()); + c.setCustomerName( "joe" ); + s.merge( c ); } ); @@ -384,15 +374,13 @@ public class ImmutableTest extends BaseSessionFactoryFunctionalTest { assertUpdateCount( 0 ); clearCounts(); - contract.setCustomerName( "joe" ); - inTransaction( s -> { - s.refresh( contract ); - assertTrue( s.isReadOnly( contract ) ); - assertEquals( "gavin", contract.getCustomerName() ); - assertEquals( 2, contract.getVariations().size() ); - Iterator it = contract.getVariations().iterator(); + Contract c = s.get(Contract.class, contract.getId()); + assertTrue( s.isReadOnly( c ) ); + assertEquals( "gavin", c.getCustomerName() ); + assertEquals( 2, c.getVariations().size() ); + Iterator it = c.getVariations().iterator(); ContractVariation cv1 = it.next(); assertEquals( "expensive", cv1.getText() ); ContractVariation cv2 = it.next(); @@ -401,11 +389,6 @@ public class ImmutableTest extends BaseSessionFactoryFunctionalTest { assertTrue( s.isReadOnly( cv2 ) ); } ); - // refresh updated detached - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - clearCounts(); inTransaction( s -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java index 7bd0f6d584..8dd589b7cd 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java @@ -9,15 +9,12 @@ import java.util.Iterator; import org.hibernate.LockMode; import org.hibernate.StaleObjectStateException; import org.hibernate.StaleStateException; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.metamodel.MappingMetamodel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -32,6 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -40,7 +38,6 @@ import static org.junit.jupiter.api.Assertions.fail; * @author Gail Badner */ @SessionFactory(generateStatistics = true) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public abstract class AbstractEntityWithManyToManyTest { private boolean isPlanContractsInverse; private boolean isPlanContractsBidirectional; @@ -171,9 +168,12 @@ public abstract class AbstractEntityWithManyToManyTest { scope.inTransaction( s -> { - s.lock( c, LockMode.NONE ); + assertThrows(IllegalArgumentException.class, + () -> s.lock( c, LockMode.NONE ), + "Given entity is not associated with the persistence context" + ); Plan p = new Plan( "plan" ); - p.addContract( c ); + p.addContract( s.get(Contract.class, c.getId()) ); s.persist( p ); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclass/JoinedSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclass/JoinedSubclassTest.java index d74d36ce21..20d6f929cd 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclass/JoinedSubclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclass/JoinedSubclassTest.java @@ -12,12 +12,9 @@ import jakarta.persistence.criteria.Root; import org.hibernate.LockMode; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -33,16 +30,15 @@ import static org.junit.jupiter.api.Assertions.assertSame; xmlMappings = "org/hibernate/orm/test/joinedsubclass/Person.hbm.xml" ) @SessionFactory -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class JoinedSubclassTest { @AfterEach public void tearDown(SessionFactoryScope scope) { scope.inTransaction( session -> { - session.createQuery( "delete from Employee" ).executeUpdate(); - session.createQuery( "delete from Customer" ).executeUpdate(); - session.createQuery( "delete from Person" ).executeUpdate(); + session.createMutationQuery( "delete from Employee" ).executeUpdate(); + session.createMutationQuery( "delete from Customer" ).executeUpdate(); + session.createMutationQuery( "delete from Person" ).executeUpdate(); } ); } @@ -63,15 +59,15 @@ public class JoinedSubclassTest { Customer c = scope.fromTransaction( session -> - session.get( Customer.class, new Long( e.getId() ) ) + session.get( Customer.class, e.getId() ) ); assertNull( c ); scope.inTransaction( session -> { - Employee employee = session.get( Employee.class, new Long( e.getId() ) ); - Customer customer = session.get( Customer.class, new Long( e.getId() ) ); + Employee employee = session.get( Employee.class, e.getId() ); + Customer customer = session.get( Customer.class, e.getId() ); assertNotNull( employee ); assertNull( customer ); } @@ -148,8 +144,8 @@ public class JoinedSubclassTest { scope.inTransaction( session -> { - session.lock( p, LockMode.PESSIMISTIC_WRITE ); - session.lock( q, LockMode.PESSIMISTIC_WRITE ); + session.lock( session.get(Person.class, p.getId()), LockMode.PESSIMISTIC_WRITE ); + session.lock( session.get( Employee.class, q.getId()), LockMode.PESSIMISTIC_WRITE ); session.remove( p ); session.remove( q ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/MergeWithTransientNonCascadedAssociationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/MergeWithTransientNonCascadedAssociationTest.java index 45fa309d5b..d1ff9fbedd 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/MergeWithTransientNonCascadedAssociationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/MergeWithTransientNonCascadedAssociationTest.java @@ -9,15 +9,12 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; -import org.hibernate.LockMode; -import org.hibernate.Session; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; -import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.fail; @@ -26,9 +23,16 @@ import static org.junit.jupiter.api.Assertions.fail; * @author Steve Ebersole */ @Jpa(annotatedClasses = {MergeWithTransientNonCascadedAssociationTest.Person.class, - MergeWithTransientNonCascadedAssociationTest.Address.class}, - properties = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) + MergeWithTransientNonCascadedAssociationTest.Address.class}) public class MergeWithTransientNonCascadedAssociationTest { + + @AfterAll + public void tearDown(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> entityManager.createQuery( "delete from Person" ).executeUpdate() + ); + } + @Test public void testMergeWithTransientNonCascadedAssociation(EntityManagerFactoryScope scope) { Person person = new Person(); @@ -54,14 +58,6 @@ public class MergeWithTransientNonCascadedAssociationTest { } } ); - - scope.inTransaction( - entityManager -> { - person.address = null; - entityManager.unwrap( Session.class ).lock( person, LockMode.NONE ); - entityManager.unwrap( Session.class ).remove( person ); - } - ); } @Entity(name = "Person") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java deleted file mode 100644 index 6eff1724cd..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.jpa.refresh; - -import org.hibernate.Session; -import org.hibernate.cfg.AvailableSettings; - -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; -import org.hibernate.testing.orm.junit.Jpa; -import org.hibernate.testing.orm.junit.Setting; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author Andrea Boriero - */ -@JiraKey(value = "HHH-11188") -@Jpa( - annotatedClasses = { - TestEntity.class - }, - integrationSettings = { @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true") } -) -public class RefreshDetachedInstanceWhenIsAllowedTest { - private TestEntity testEntity; - - @BeforeEach - public void setUp(EntityManagerFactoryScope scope) { - testEntity = new TestEntity(); - scope.inTransaction( - entityManager -> { - entityManager.persist( testEntity ); - } - ); - } - - @AfterEach - public void tearDown(EntityManagerFactoryScope scope) { - scope.inTransaction( - entityManager -> { - entityManager.createQuery( "delete from TestEntity" ).executeUpdate(); - } - ); - } - - @Test - public void testUnwrappedSessionRefreshDetachedInstance(EntityManagerFactoryScope scope) { - scope.inEntityManager( - entityManager -> { - final Session session = entityManager.unwrap( Session.class ); - session.refresh( testEntity ); - } - ); - } - - @Test - public void testRefreshDetachedInstance(EntityManagerFactoryScope scope) { - scope.inEntityManager( - entityManager -> { - entityManager.refresh( testEntity ); - } - ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java deleted file mode 100644 index f86cc71138..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.jpa.refresh; - -import org.hibernate.Session; - -import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; -import org.hibernate.testing.orm.junit.Jpa; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author Andrea Boriero - */ -@Jpa( - annotatedClasses = { - TestEntity.class - } -) -public class RefreshDetachedInstanceWhenIsNotAllowedTest { - private TestEntity testEntity; - - @BeforeEach - public void setUp(EntityManagerFactoryScope scope) { - testEntity = new TestEntity(); - scope.inTransaction( - entityManager -> { - entityManager.persist( testEntity ); - } - ); - } - - @AfterEach - public void tearDown(EntityManagerFactoryScope scope) { - scope.inTransaction( - entityManager -> { - entityManager.createQuery( "delete from TestEntity" ).executeUpdate(); - } - ); - } - - @Test - public void testUnwrappedSessionRefreshDetachedInstance(EntityManagerFactoryScope scope) { - scope.inTransaction( - entityManager -> { - final Session session = entityManager.unwrap( Session.class ); - Assertions.assertThrows( - IllegalArgumentException.class, - () -> session.refresh( testEntity ), - "Should have thrown an IllegalArgumentException" - ); - } - ); - } - - @Test - public void testRefreshDetachedInstance(EntityManagerFactoryScope scope) { - scope.inTransaction( - entityManager -> { - Assertions.assertThrows( - IllegalArgumentException.class, - () -> entityManager.refresh( testEntity ), - "Should have thrown an IllegalArgumentException" - ); - } - ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/TestEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/TestEntity.java deleted file mode 100644 index 55b8607e05..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/refresh/TestEntity.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.jpa.refresh; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; - -/** - * @author Andrea Boriero - */ -@Entity -public class TestEntity { - @Id - @GeneratedValue - public long id; -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdNonStrictReadWriteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdNonStrictReadWriteTest.java index 1c58ffb0d1..dc34ca83db 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdNonStrictReadWriteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdNonStrictReadWriteTest.java @@ -10,7 +10,6 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.Setting; -import static org.hibernate.cfg.AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY; import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS; import static org.hibernate.cfg.AvailableSettings.USE_SECOND_LEVEL_CACHE; import static org.hibernate.testing.cache.CachingRegionFactory.DEFAULT_ACCESSTYPE; @@ -19,8 +18,7 @@ import static org.hibernate.testing.cache.CachingRegionFactory.DEFAULT_ACCESSTYP settings = { @Setting( name = USE_SECOND_LEVEL_CACHE, value = "true" ), @Setting( name = DEFAULT_ACCESSTYPE, value = "nonstrict-read-write" ), - @Setting( name = GENERATE_STATISTICS, value = "true" ), - @Setting( name = ALLOW_REFRESH_DETACHED_ENTITY, value = "true" ) + @Setting( name = GENERATE_STATISTICS, value = "true" ) } ) @DomainModel( annotatedClasses = {A.class, Another.class, AllCached.class, B.class, SubClass.class} ) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdStrictReadWriteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdStrictReadWriteTest.java index 7b5cf04c26..b2ee02eb33 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdStrictReadWriteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdStrictReadWriteTest.java @@ -16,7 +16,6 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.Test; -import static org.hibernate.cfg.AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY; import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS; import static org.hibernate.cfg.AvailableSettings.USE_SECOND_LEVEL_CACHE; import static org.hibernate.testing.cache.CachingRegionFactory.DEFAULT_ACCESSTYPE; @@ -28,8 +27,7 @@ import static org.junit.Assert.assertNull; settings = { @Setting( name = USE_SECOND_LEVEL_CACHE, value = "true" ), @Setting( name = DEFAULT_ACCESSTYPE, value = "nonstrict-read-write" ), - @Setting( name = GENERATE_STATISTICS, value = "true" ), - @Setting( name = ALLOW_REFRESH_DETACHED_ENTITY, value = "true" ) + @Setting( name = GENERATE_STATISTICS, value = "true" ) } ) @DomainModel( annotatedClasses = {A.class, Another.class, AllCached.class, B.class, SubClass.class} ) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdTest.java index 45e83056e5..b8ca513eb3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/mutable/cached/CachedMutableNaturalIdTest.java @@ -4,7 +4,6 @@ */ package org.hibernate.orm.test.mapping.naturalid.mutable.cached; -import org.hibernate.LockOptions; import org.hibernate.cache.spi.CacheImplementor; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.stat.spi.StatisticsImplementor; @@ -274,38 +273,4 @@ public abstract class CachedMutableNaturalIdTest { }); } - @Test - public void testReattachUnmodifiedInstance(SessionFactoryScope scope) { - final B created = scope.fromTransaction( - (session) -> { - A a = new A(); - B b = new B(); - b.naturalid = 100; - session.persist( a ); - session.persist( b ); - b.assA = a; - a.assB.add( b ); - - return b; - } - ); - - scope.inTransaction( - (session) -> { - // HHH-7513 failure during reattachment - session.lock( created, LockOptions.NONE ); - session.remove( created.assA ); - session.remove( created ); - } - ); - - scope.inTransaction( - (session) -> { - // true if the re-attachment worked - assertEquals( session.createQuery( "FROM A" ).list().size(), 0 ); - assertEquals( session.createQuery( "FROM B" ).list().size(), 0 ); - } - ); - } - } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/OrphanTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/OrphanTest.java index 8913571c84..017c61c231 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/OrphanTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/OrphanTest.java @@ -6,19 +6,17 @@ package org.hibernate.orm.test.orphan; import org.hibernate.Hibernate; import org.hibernate.LockMode; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -28,7 +26,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; xmlMappings = "org/hibernate/orm/test/orphan/Product.hbm.xml" ) @SessionFactory -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class OrphanTest { @AfterEach @@ -138,7 +135,7 @@ public class OrphanTest { @Test @SuppressWarnings("unchecked") - public void testOrphanDeleteAfterLock(SessionFactoryScope scope) { + public void testCannotLockDetachedEntity(SessionFactoryScope scope) { Product prod = new Product(); Part part = new Part(); scope.inTransaction( @@ -158,14 +155,16 @@ public class OrphanTest { scope.inTransaction( session -> { - session.lock( prod, LockMode.READ ); - prod.getParts().remove( part ); + assertThrows(IllegalArgumentException.class, + () -> session.lock( prod, LockMode.READ ), + "Given entity is not associated with the persistence context" + ); } ); scope.inTransaction( session -> { - assertNull( session.get( Part.class, "Widge" ) ); + assertNotNull( session.get( Part.class, "Widge" ) ); assertNotNull( session.get( Part.class, "Get" ) ); session.remove( session.get( Product.class, "Widget" ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyProxyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyProxyTest.java index 9603a2b4e7..e669d26624 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyProxyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyProxyTest.java @@ -10,17 +10,13 @@ import org.hibernate.CacheMode; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.UnresolvableObjectException; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.FailureExpected; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -42,7 +38,6 @@ import static org.junit.jupiter.api.Assertions.fail; "org/hibernate/orm/test/readonly/TextHolder.hbm.xml" } ) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class ReadOnlyProxyTest extends AbstractReadOnlyTest { @Test @@ -1156,9 +1151,9 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest { s.flush(); try { s.refresh( dp ); - fail( "should have thrown UnresolvableObjectException" ); + fail( "should have thrown IllegalArgumentException" ); } - catch (UnresolvableObjectException ex) { + catch (IllegalArgumentException ex) { // expected } finally { @@ -1182,9 +1177,9 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest { assertTrue( Hibernate.isInitialized( dpProxyInit ) ); try { s.refresh( dpProxyInit ); - fail( "should have thrown UnresolvableObjectException" ); + fail( "should have thrown IllegalArgumentException" ); } - catch (UnresolvableObjectException ex) { + catch (IllegalArgumentException ex) { // expected } finally { @@ -1199,9 +1194,9 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest { s.refresh( dpProxy ); assertFalse( Hibernate.isInitialized( dpProxy ) ); Hibernate.initialize( dpProxy ); - fail( "should have thrown UnresolvableObjectException" ); + fail( "should have thrown IllegalArgumentException" ); } - catch (UnresolvableObjectException ex) { + catch (IllegalArgumentException ex) { // expected } finally { @@ -1210,50 +1205,6 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest { } } - @Test - public void testReadOnlyRefreshDetached(SessionFactoryScope scope) { - Session s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - Transaction t = s.beginTransaction(); - DataPoint dp = new DataPoint(); - dp.setDescription( "original" ); - dp.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - s.persist( dp ); - t.commit(); - s.close(); - - s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - t = s.beginTransaction(); - dp = s.getReference( DataPoint.class, dp.getId() ); - assertFalse( Hibernate.isInitialized( dp ) ); - assertFalse( s.isReadOnly( dp ) ); - s.setReadOnly( dp, true ); - assertTrue( s.isReadOnly( dp ) ); - s.evict( dp ); - s.refresh( dp ); - assertTrue( Hibernate.isInitialized( dp ) ); - assertFalse( s.isReadOnly( dp ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - assertTrue( Hibernate.isInitialized( dp ) ); - s.setReadOnly( dp, true ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - t.commit(); - - s.clear(); - t = s.beginTransaction(); - dp = s.get( DataPoint.class, dp.getId() ); - assertEquals( "original", dp.getDescription() ); - s.remove( dp ); - t.commit(); - s.close(); - } - @Test public void testReadOnlyProxyMergeDetachedProxyWithChange(SessionFactoryScope scope) { DataPoint dpOrig = createDataPoint( CacheMode.IGNORE, scope ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlySessionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlySessionTest.java index 8eeb1b5864..cb1cd50414 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlySessionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlySessionTest.java @@ -13,14 +13,11 @@ import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.proxy.HibernateProxy; import org.hibernate.query.Query; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -39,7 +36,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; "org/hibernate/orm/test/readonly/TextHolder.hbm.xml" } ) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class ReadOnlySessionTest extends AbstractReadOnlyTest { @AfterEach @@ -450,53 +446,6 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest { s.close(); } - @Test - public void testReadOnlyRefreshDetached(SessionFactoryScope scope) { - Session s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - Transaction t = s.beginTransaction(); - DataPoint dp = new DataPoint(); - dp.setDescription( "original" ); - dp.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - s.persist( dp ); - t.commit(); - s.close(); - - s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - t = s.beginTransaction(); - s.setDefaultReadOnly( false ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.setDefaultReadOnly( true ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertTrue( s.isReadOnly( dp ) ); - dp.setDescription( "changed" ); - t.commit(); - - s.clear(); - t = s.beginTransaction(); - dp = s.get( DataPoint.class, dp.getId() ); - assertEquals( "original", dp.getDescription() ); - s.remove( dp ); - t.commit(); - s.close(); - } - @Test public void testReadOnlyProxyRefresh(SessionFactoryScope scope) { Session s = openSession( scope ); @@ -554,65 +503,6 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest { } - @Test - public void testReadOnlyProxyRefreshDetached(SessionFactoryScope scope) { - Session s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - Transaction t = s.beginTransaction(); - DataPoint dp = new DataPoint(); - dp.setDescription( "original" ); - dp.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - s.persist( dp ); - t.commit(); - s.close(); - - s = openSession( scope ); - s.setCacheMode( CacheMode.IGNORE ); - t = s.beginTransaction(); - s.setDefaultReadOnly( true ); - dp = (DataPoint) s.getReference( DataPoint.class, dp.getId() ); - assertFalse( Hibernate.isInitialized( dp ) ); - assertTrue( s.isReadOnly( dp ) ); - s.evict( dp ); - s.refresh( dp ); - assertTrue( Hibernate.isInitialized( dp ) ); - s.setDefaultReadOnly( false ); - assertTrue( s.isReadOnly( dp ) ); - s.evict( dp ); - s.refresh( dp ); - assertTrue( Hibernate.isInitialized( dp ) ); - assertFalse( s.isReadOnly( dp ) ); - assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - assertTrue( Hibernate.isInitialized( dp ) ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.setDefaultReadOnly( true ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertTrue( s.isReadOnly( dp ) ); - assertTrue( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - t.commit(); - - s.clear(); - t = s.beginTransaction(); - dp = s.get( DataPoint.class, dp.getId() ); - assertEquals( "original", dp.getDescription() ); - s.remove( dp ); - t.commit(); - s.close(); - } - @Test public void testReadOnlyDelete(SessionFactoryScope scope) { Session s = openSession( scope ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyTest.java index 0662a05415..5ce7ad2ba9 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyTest.java @@ -13,11 +13,8 @@ import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -36,7 +33,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; "org/hibernate/orm/test/readonly/TextHolder.hbm.xml" } ) -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) public class ReadOnlyTest extends AbstractReadOnlyTest { @Test @@ -317,55 +313,6 @@ public class ReadOnlyTest extends AbstractReadOnlyTest { clearCounts( scope ); } - @Test - public void testReadOnlyRefreshDetached(SessionFactoryScope scope) { - clearCounts( scope ); - - Session s = openSession( scope ); - Transaction t = s.beginTransaction(); - DataPoint dp = new DataPoint(); - dp.setDescription( "original" ); - dp.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - s.persist( dp ); - t.commit(); - s.close(); - - assertInsertCount( 1, scope ); - assertUpdateCount( 0, scope ); - clearCounts( scope ); - - s = openSession( scope ); - t = s.beginTransaction(); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - s.setReadOnly( dp, true ); - dp.setDescription( "changed" ); - assertEquals( "changed", dp.getDescription() ); - s.evict( dp ); - s.refresh( dp ); - assertEquals( "original", dp.getDescription() ); - assertFalse( s.isReadOnly( dp ) ); - t.commit(); - - assertInsertCount( 0, scope ); - assertUpdateCount( 0, scope ); - - s.clear(); - t = s.beginTransaction(); - dp = (DataPoint) s.get( DataPoint.class, dp.getId() ); - assertEquals( "original", dp.getDescription() ); - s.remove( dp ); - t.commit(); - s.close(); - - assertUpdateCount( 0, scope ); - assertDeleteCount( 1, scope ); - } - @Test public void testReadOnlyDelete(SessionFactoryScope scope) { clearCounts( scope ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java deleted file mode 100644 index e423a0f247..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsAllowedTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.refresh; - -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.orm.test.jpa.refresh.TestEntity; - -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; -import org.hibernate.testing.orm.junit.SessionFactory; -import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author Andrea Boriero - */ -@JiraKey(value = "HHH-11188") -@DomainModel( - annotatedClasses = TestEntity.class -) -@SessionFactory -@ServiceRegistry(settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) -public class RefreshDetachedInstanceWhenIsAllowedTest { - private TestEntity testEntity; - - @BeforeEach - public void setUp(SessionFactoryScope scope) { - testEntity = new TestEntity(); - scope.inTransaction( - session -> - session.persist( testEntity ) - ); - } - - @AfterEach - public void tearDown(SessionFactoryScope scope) { - scope.inTransaction( - session -> - session.createQuery( "delete from TestEntity" ).executeUpdate() - ); - } - - @Test - public void testRefreshDetachedInstance(SessionFactoryScope scope) { - scope.inSession( - session -> - session.refresh( testEntity ) - ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java deleted file mode 100644 index 9cff5f6fdd..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/refresh/RefreshDetachedInstanceWhenIsNotAllowedTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.refresh; - -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.orm.test.jpa.refresh.TestEntity; - -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.ServiceRegistry; -import org.hibernate.testing.orm.junit.SessionFactory; -import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.hibernate.testing.orm.junit.Setting; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author Andrea Boriero - */ -@DomainModel( - annotatedClasses = TestEntity.class -) -@SessionFactory -@ServiceRegistry( - settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "false") -) -public class RefreshDetachedInstanceWhenIsNotAllowedTest { - private TestEntity testEntity; - - @BeforeEach - public void setUp(SessionFactoryScope scope) { - testEntity = new TestEntity(); - scope.inTransaction( - session -> - session.persist( testEntity ) - ); - } - - @AfterEach - public void tearDown(SessionFactoryScope scope) { - scope.inTransaction( - session -> - session.createQuery( "delete from TestEntity" ).executeUpdate() - ); - } - - @Test - public void testRefreshDetachedInstance(SessionFactoryScope scope) { - scope.inSession( - session -> - Assertions.assertThrows( - IllegalArgumentException.class, () -> - session.refresh( testEntity ) - ) - ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/session/AssociateEntityWithTwoSessionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/session/AssociateEntityWithTwoSessionsTest.java deleted file mode 100644 index d971aee455..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/session/AssociateEntityWithTwoSessionsTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-2.1-or-later - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.orm.test.session; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; - -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.proxy.AbstractLazyInitializer; - -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.logger.LoggerInspectionRule; -import org.hibernate.testing.logger.Triggerable; -import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; -import org.hibernate.testing.orm.junit.Jpa; - -import org.hibernate.testing.orm.junit.Setting; -import org.junit.Rule; -import org.junit.jupiter.api.Test; - -import org.jboss.logging.Logger; - -import java.lang.invoke.MethodHandles; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Vlad Mihalcea - */ -@Jpa(annotatedClasses = {AssociateEntityWithTwoSessionsTest.Location.class, - AssociateEntityWithTwoSessionsTest.Event.class}, - properties = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true")) -public class AssociateEntityWithTwoSessionsTest { - - @Rule - public LoggerInspectionRule logInspection = new LoggerInspectionRule( - Logger.getMessageLogger( MethodHandles.lookup(), CoreMessageLogger.class, AbstractLazyInitializer.class.getName() ) ); - - @Test - @JiraKey( value = "HHH-12216" ) - public void test(EntityManagerFactoryScope scope) { - - final Location location = new Location(); - location.setCity( "Cluj" ); - - final Event event = new Event(); - event.setLocation( location ); - - scope.inTransaction( entityManager -> { - entityManager.persist( location ); - entityManager.persist( event ); - } ); - - final Triggerable triggerable = logInspection.watchForLogMessages( "HHH000485" ); - triggerable.reset(); - - scope.inTransaction( entityManager -> { - Event e = entityManager.find( Event.class, event.id ); - Location location1 = e.getLocation(); - - try { - scope.inTransaction( _entityManager -> { - _entityManager.unwrap( Session.class ).lock( location1, LockMode.NONE ); - } ); - - fail("Should have thrown a HibernateException"); - } - catch (Exception expected) { - } - } ); - - assertEquals( - "HHH000485: Illegally attempted to associate a proxy for entity [org.hibernate.orm.test.session.AssociateEntityWithTwoSessionsTest$Location] with id [1] with two open sessions.", - triggerable.triggerMessage() - ); - - } - - @Entity(name = "Location") - public static class Location { - - @Id - @GeneratedValue - public Long id; - - public String city; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - } - - @Entity(name = "Event") - public static class Event { - - @Id - @GeneratedValue - public Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Location location; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Location getLocation() { - return location; - } - - public void setLocation(Location location) { - this.location = location; - } - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/ParameterMarkerStrategyTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/ParameterMarkerStrategyTests.java index f5df4bd9fb..14e932dc31 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/ParameterMarkerStrategyTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/ParameterMarkerStrategyTests.java @@ -6,14 +6,11 @@ package org.hibernate.orm.test.sql.ast; import java.util.List; -import org.hibernate.LockMode; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.ParamDef; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.H2Dialect; import org.hibernate.sql.ast.spi.ParameterMarkerStrategy; -import org.hibernate.testing.orm.junit.Setting; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.testing.jdbc.SQLStatementInspector; @@ -45,8 +42,8 @@ import static org.hibernate.internal.util.StringHelper.*; */ @ServiceRegistry( services = @ServiceRegistry.Service( role = ParameterMarkerStrategy.class, - impl = ParameterMarkerStrategyTests.ParameterMarkerStrategyImpl.class -), settings = @Setting(name = AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY, value = "true") ) + impl = ParameterMarkerStrategyTests.ParameterMarkerStrategyImpl.class ) +) @DomainModel( annotatedClasses = { EntityOfBasics.class, ParameterMarkerStrategyTests.EntityWithFilters.class, @@ -127,28 +124,6 @@ public class ParameterMarkerStrategyTests { } ); } - @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-16229" ) - public void testLocking(SessionFactoryScope scope) { - final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector(); - - final EntityWithVersion created = scope.fromTransaction( (session) -> { - final EntityWithVersion entity = new EntityWithVersion( 1, "Entity Prime" ); - session.persist( entity ); - return entity; - } ); - - statementInspector.clear(); - scope.inTransaction( (session) -> { - session.lock( created, LockMode.PESSIMISTIC_FORCE_INCREMENT ); - assertThat( statementInspector.getSqlQueries() ).hasSize( 1 ); - assertThat( statementInspector.getSqlQueries().get( 0 ) ).contains( "?1" ); - assertThat( statementInspector.getSqlQueries().get( 0 ) ).contains( "?2" ); - assertThat( statementInspector.getSqlQueries().get( 0 ) ).contains( "?3" ); - assertThat( statementInspector.getSqlQueries().get( 0 ) ).matches( (sql) -> count( sql, "?" ) == 3 ); - } ); - } - @Test @FailureExpected @Jira( "https://hibernate.atlassian.net/browse/HHH-16283" ) diff --git a/migration-guide.adoc b/migration-guide.adoc index 6f8b7e8b6a..2b8d033047 100644 --- a/migration-guide.adoc +++ b/migration-guide.adoc @@ -245,6 +245,16 @@ parent.addChild( merged ); ---- +[[refresh-lock-deteached]] +== Refreshing/locking detached entities + +Traditionally, Hibernate allowed detached entities to be refreshed. However, Jakarta Persistence prohibits this practice and specifies that an `IllegalArgumentException` should be thrown instead. Hibernate now fully aligns with the JPA specification in this regard. + +Along the same line of thought, also acquiring a lock on a detached entity is no longer allowed. + +To this effect the `hibernate.allow_refresh_detached_entity`, which allowed Hibernate's legacy refresh behaviour to be invoked, has been removed. + + [[auto-cascade-persist]] == Cascading persistence for `@Id` and `@MapsId` fields @@ -377,6 +387,7 @@ While most users will never see this change, it might impact integrations which * Settings ** Removed `hibernate.mapping.precedence` and friends +** Removed `hibernate.allow_refresh_detached_entity`