From d6518e0c7a5f2453b8dde5dadf5ea53300de98ae Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 28 Jun 2021 15:38:02 +0200 Subject: [PATCH] Re-enabled additional tests --- .../envers/QueryAuditAdressCountryTest.java | 1 - .../EventListenerDuplicationStrategyTest.java | 54 +- .../EventListenerGroupAppendListenerTest.java | 27 +- ...antiatdCollectionSkipDeleteOrphanTest.java | 330 ++--- .../test/common/JournalingBatchObserver.java | 2 +- .../common/JournalingConnectionObserver.java | 2 +- .../common/JournalingTransactionObserver.java | 2 +- .../test}/event/EmbeddableCallbackTest.java | 47 +- .../orm/test/jdbc/internal/BatchingTest.java | 2 +- ...azyPersistWithDetachedAssociationTest.java | 78 +- ...bstractManyToManyAssociationClassTest.java | 255 ++++ .../manytomanyassociationclass/Group.java | 2 +- .../Membership.java | 2 +- .../test/manytomanyassociationclass/User.java | 2 +- ...ToManyAssociationClassCompositeIdTest.java | 24 +- .../compositeid/Mappings.hbm.xml | 10 +- .../MembershipWithCompositeId.java | 8 +- ...yToManyAssociationClassAssignedIdTest.java | 15 +- .../surrogateid/assigned/Mappings.hbm.xml | 2 +- ...ToManyAssociationClassGeneratedIdTest.java | 121 ++ .../surrogateid/generated/Mappings.hbm.xml | 2 +- .../{ => orm}/test/ondelete/Address.java | 2 +- .../{ => orm}/test/ondelete/Employee.java | 2 +- .../orm/test/ondelete/OnDeleteTest.java | 103 ++ .../{ => orm}/test/ondelete/Person.hbm.xml | 2 +- .../{ => orm}/test/ondelete/Person.java | 2 +- .../{ => orm}/test/ondelete/Salesperson.java | 2 +- .../ondelete/toone/ToOneOnDeleteTest.java | 127 ++ .../test/ondelete/toone/hbm/Child.java | 2 +- .../test/ondelete/toone/hbm/GrandChild.java | 2 +- .../test/ondelete/toone/hbm/Parent.java | 2 +- .../ondelete/toone/hbm/ToOneOnDelete.hbm.xml | 2 +- .../toone/hbm/ToOneOnDeleteHbmTest.java | 84 ++ .../test/ondemandload/Inventory.java | 2 +- .../test/ondemandload/LazyLoadingTest.java | 182 +++ .../{ => orm}/test/ondemandload/Product.java | 2 +- .../{ => orm}/test/ondemandload/Store.java | 2 +- .../cache/CacheLazyLoadNoTransTest.java | 227 ++++ .../test/ops/AbstractOperationTestCase.java | 65 + .../hibernate/{ => orm}/test/ops/Address.java | 2 +- .../{ => orm}/test/ops/Category.java | 2 +- .../{ => orm}/test/ops/Competition.hbm.xml | 2 +- .../{ => orm}/test/ops/Competition.java | 2 +- .../{ => orm}/test/ops/Competitor.java | 2 +- .../hibernate/orm/test/ops/CreateTest.java | 244 ++++ .../test/ops/CustomEntityCopyObserver.java | 28 + .../hibernate/orm/test/ops/DeleteTest.java | 94 ++ .../{ => orm}/test/ops/Employee.java | 2 +- .../{ => orm}/test/ops/Employer.hbm.xml | 2 +- .../{ => orm}/test/ops/Employer.java | 2 +- .../hibernate/orm/test/ops/GetLoadTest.java | 141 ++ .../orm/test/ops/HANANoColumnInsertTest.java | 64 + .../{ => orm}/test/ops/Hoarder.hbm.xml | 2 +- .../hibernate/{ => orm}/test/ops/Hoarder.java | 2 +- .../test/ops/HoarderOrphanDelete.hbm.xml | 2 +- .../hibernate/{ => orm}/test/ops/Item.java | 2 +- .../ops/MergeManagedAndCopiesAllowedTest.java | 89 +- ...MultipleEntityCopiesAllowedLoggedTest.java | 17 +- ...leEntityCopiesAllowedOrphanDeleteTest.java | 495 +++++++ .../MergeMultipleEntityCopiesAllowedTest.java | 1198 ++++++++++++++++ .../MergeMultipleEntityCopiesCustomTest.java | 193 +++ ...leEntityCopiesDisallowedByDefaultTest.java | 145 ++ ...rgeMultipleEntityCopiesDisallowedTest.java | 19 +- .../org/hibernate/orm/test/ops/MergeTest.java | 850 ++++++++++++ .../hibernate/{ => orm}/test/ops/Node.hbm.xml | 2 +- .../hibernate/{ => orm}/test/ops/Node.java | 3 +- .../{ => orm}/test/ops/NumberedNode.java | 2 +- .../{ => orm}/test/ops/OneToOne.hbm.xml | 2 +- .../{ => orm}/test/ops/OneToOneMergeTest.java | 66 +- .../{ => orm}/test/ops/OptLockEntity.hbm.xml | 2 +- .../test/ops/OracleNoColumnInsertTest.java | 38 + .../hibernate/{ => orm}/test/ops/Person.java | 2 +- .../{ => orm}/test/ops/PersonalDetails.java | 2 +- .../test/ops/RemoveOrderingTest.java | 56 +- .../orm/test/ops/SaveOrUpdateTest.java | 533 ++++++++ .../{ => orm}/test/ops/SimpleEntity.hbm.xml | 2 +- .../{ => orm}/test/ops/SimpleEntity.java | 2 +- .../hibernate/orm/test/ops/SimpleOpsTest.java | 110 ++ .../{ => orm}/test/ops/SubCategory.java | 2 +- .../hibernate/{ => orm}/test/ops/SubItem.java | 2 +- .../{ => orm}/test/ops/TimestampedEntity.java | 2 +- .../{ => orm}/test/ops/VersionedEntity.java | 2 +- .../genericApi/BasicGetLoadAccessTest.java | 269 ++-- .../genericApi/ProxiedGetLoadAccessTest.java | 208 ++- .../test/unionsubclass2/Address.java | 2 +- .../test/unionsubclass2/Customer.java | 2 +- .../test/unionsubclass2/Employee.java | 2 +- .../test/unionsubclass2/Person.hbm.xml | 2 +- .../{ => orm}/test/unionsubclass2/Person.java | 2 +- .../unionsubclass2/UnionSubclassTest.java | 50 +- .../ExtraLazyCollectionConsistencyTest.java | 154 ++- .../test/extralazy/ExtraLazyTest.java | 602 ++++---- ...bstractManyToManyAssociationClassTest.java | 260 ---- ...ToManyAssociationClassGeneratedIdTest.java | 122 -- .../hibernate/test/ondelete/OnDeleteTest.java | 96 -- .../ondelete/toone/ToOneOnDeleteTest.java | 111 -- .../toone/hbm/ToOneOnDeleteHbmTest.java | 73 - .../test/ondemandload/LazyLoadingTest.java | 174 --- .../cache/CacheLazyLoadNoTransTest.java | 201 --- .../test/ops/AbstractOperationTestCase.java | 59 - .../org/hibernate/test/ops/CreateTest.java | 236 ---- .../org/hibernate/test/ops/DeleteTest.java | 95 -- .../org/hibernate/test/ops/GetLoadTest.java | 136 -- .../test/ops/HANANoColumnInsertTest.java | 49 - ...leEntityCopiesAllowedOrphanDeleteTest.java | 508 ------- .../MergeMultipleEntityCopiesAllowedTest.java | 1208 ----------------- .../MergeMultipleEntityCopiesCustomTest.java | 218 --- ...leEntityCopiesDisallowedByDefaultTest.java | 156 --- .../org/hibernate/test/ops/MergeTest.java | 851 ------------ .../test/ops/OracleNoColumnInsertTest.java | 40 - .../hibernate/test/ops/SaveOrUpdateTest.java | 528 ------- .../org/hibernate/test/ops/SimpleOpsTest.java | 110 -- .../BaseSessionFactoryFunctionalTest.java | 82 +- .../orm/junit/SessionFactoryExtension.java | 2 - 114 files changed, 6521 insertions(+), 6318 deletions(-) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/common/JournalingBatchObserver.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/common/JournalingConnectionObserver.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/common/JournalingTransactionObserver.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm/test}/event/EmbeddableCallbackTest.java (54%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java (57%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/Group.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/Membership.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/User.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java (55%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml (83%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java (88%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java (58%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml (95%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/Address.java (91%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/Employee.java (96%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/OnDeleteTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/Person.hbm.xml (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/Person.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/Salesperson.java (93%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/ToOneOnDeleteTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/toone/hbm/Child.java (91%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/toone/hbm/GrandChild.java (91%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/toone/hbm/Parent.java (88%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml (92%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondemandload/Inventory.java (97%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/LazyLoadingTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondemandload/Product.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ondemandload/Store.java (97%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/cache/CacheLazyLoadNoTransTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/AbstractOperationTestCase.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Address.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Category.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Competition.hbm.xml (93%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Competition.java (94%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Competitor.java (94%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/ops/CreateTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/CustomEntityCopyObserver.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/DeleteTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Employee.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Employer.hbm.xml (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Employer.java (96%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/GetLoadTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/HANANoColumnInsertTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Hoarder.hbm.xml (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Hoarder.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/HoarderOrphanDelete.hbm.xml (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Item.java (98%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/MergeManagedAndCopiesAllowedTest.java (56%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java (62%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesCustomTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/MergeMultipleEntityCopiesDisallowedTest.java (61%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Node.hbm.xml (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Node.java (98%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/NumberedNode.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/OneToOne.hbm.xml (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/OneToOneMergeTest.java (58%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/OptLockEntity.hbm.xml (95%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/ops/OracleNoColumnInsertTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/Person.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/PersonalDetails.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/RemoveOrderingTest.java (58%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/ops/SaveOrUpdateTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/SimpleEntity.hbm.xml (91%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/SimpleEntity.java (94%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleOpsTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/SubCategory.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/SubItem.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/TimestampedEntity.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/ops/VersionedEntity.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/Address.java (90%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/Customer.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/Employee.java (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/Person.hbm.xml (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/Person.java (97%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/unionsubclass2/UnionSubclassTest.java (88%) delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/ondelete/OnDeleteTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/ToOneOnDeleteTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ondemandload/LazyLoadingTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ondemandload/cache/CacheLazyLoadNoTransTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/DeleteTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/GetLoadTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesCustomTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/test/ops/OracleNoColumnInsertTest.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java diff --git a/documentation/src/test/java/org/hibernate/userguide/envers/QueryAuditAdressCountryTest.java b/documentation/src/test/java/org/hibernate/userguide/envers/QueryAuditAdressCountryTest.java index ed76e1dffa..a5fe91b869 100644 --- a/documentation/src/test/java/org/hibernate/userguide/envers/QueryAuditAdressCountryTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/envers/QueryAuditAdressCountryTest.java @@ -26,7 +26,6 @@ import org.hibernate.envers.query.AuditEntity; import org.hibernate.envers.strategy.ValidityAuditStrategy; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.orm.test.legacy.Custom; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; diff --git a/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerDuplicationStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerDuplicationStrategyTest.java index b423363dc7..aa687df31f 100644 --- a/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerDuplicationStrategyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerDuplicationStrategyTest.java @@ -11,24 +11,20 @@ import org.hibernate.event.spi.ClearEventListener; import org.hibernate.event.spi.EventType; import org.hibernate.testing.TestForIssue; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Test that a listener replacing the original one is actually called when the event is fired for each listener. *

- * Note: I'm using ClearEvent for the tests because it's the simpler one I've found. + * Note: I'm using ClearEvent for the tests because it's the simpler one I've found. *

*/ @TestForIssue(jiraKey = "HHH-13831") public class EventListenerDuplicationStrategyTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - Tracker tracker = new Tracker(); ClearEvent event = new ClearEvent( null ); EventListenerGroup listenerGroup = new EventListenerGroupImpl( EventType.CLEAR, null, false ); @@ -85,7 +81,11 @@ public class EventListenerDuplicationStrategyTest { listenerGroup.appendListener( new ExtraListener( tracker ) ); listenerGroup.listeners().forEach( listener -> listener.onClear( event ) ); - assertThat( tracker.callers ).containsExactly( OriginalListener.class, ExpectedListener.class, ExtraListener.class ); + assertThat( tracker.callers ).containsExactly( + OriginalListener.class, + ExpectedListener.class, + ExtraListener.class + ); } @Test @@ -95,7 +95,11 @@ public class EventListenerDuplicationStrategyTest { listenerGroup.appendListener( new ExtraListener( tracker ) ); listenerGroup.fireLazyEventOnEachListener( () -> event, ClearEventListener::onClear ); - assertThat( tracker.callers ).containsExactly( OriginalListener.class, ExpectedListener.class, ExtraListener.class ); + assertThat( tracker.callers ).containsExactly( + OriginalListener.class, + ExpectedListener.class, + ExtraListener.class + ); } @Test @@ -105,7 +109,11 @@ public class EventListenerDuplicationStrategyTest { listenerGroup.appendListener( new ExtraListener( tracker ) ); listenerGroup.fireEventOnEachListener( event, ClearEventListener::onClear ); - assertThat( tracker.callers ).containsExactly( OriginalListener.class, ExpectedListener.class, ExtraListener.class ); + assertThat( tracker.callers ).containsExactly( + OriginalListener.class, + ExpectedListener.class, + ExtraListener.class + ); } @Test @@ -176,12 +184,15 @@ public class EventListenerDuplicationStrategyTest { @Test public void testErrorStrategyOnAppend() { - thrown.expect( EventListenerRegistrationException.class ); - thrown.expectMessage( "Duplicate event listener found" ); - - listenerGroup.addDuplicationStrategy( ErrorStrategy.INSTANCE ); - listenerGroup.appendListener( new OriginalListener( tracker ) ); - listenerGroup.appendListener( new ExpectedListener( tracker ) ); + final EventListenerRegistrationException expectedException = assertThrows( + EventListenerRegistrationException.class, + () -> { + listenerGroup.addDuplicationStrategy( ErrorStrategy.INSTANCE ); + listenerGroup.appendListener( new OriginalListener( tracker ) ); + listenerGroup.appendListener( new ExpectedListener( tracker ) ); + } + ); + assertThat( expectedException.getMessage() ).isEqualTo( "Duplicate event listener found" ); } @Test @@ -194,10 +205,13 @@ public class EventListenerDuplicationStrategyTest { @Test public void testDefaultDuplicationStrategy() { - thrown.expect( EventListenerRegistrationException.class ); - //By default, it's not allowed to register the same type of listener twice: - listenerGroup.appendListener( new OriginalListener( tracker ) ); - listenerGroup.appendListener( new OriginalListener( tracker ) ); + assertThrows( + EventListenerRegistrationException.class, () -> { + //By default, it's not allowed to register the same type of listener twice: + listenerGroup.appendListener( new OriginalListener( tracker ) ); + listenerGroup.appendListener( new OriginalListener( tracker ) ); + } + ); } /** diff --git a/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerGroupAppendListenerTest.java b/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerGroupAppendListenerTest.java index f6d1d21a38..aee79fae0b 100644 --- a/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerGroupAppendListenerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/event/service/internal/EventListenerGroupAppendListenerTest.java @@ -6,11 +6,6 @@ */ package org.hibernate.event.service.internal; -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import java.lang.reflect.Field; import org.hibernate.event.internal.DefaultMergeEventListener; @@ -21,15 +16,20 @@ import org.hibernate.event.spi.EventType; import org.hibernate.event.spi.MergeEventListener; import org.hibernate.jpa.event.spi.CallbackRegistry; import org.hibernate.service.spi.ServiceRegistryImplementor; + import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** * @author Frank Doherty */ @TestForIssue(jiraKey = "HHH-13070") -public class EventListenerGroupAppendListenerTest extends BaseCoreFunctionalTestCase { +public class EventListenerGroupAppendListenerTest extends BaseSessionFactoryFunctionalTest { private static final DuplicationStrategy DUPLICATION_STRATEGY_REPLACE_ORIGINAL = new DuplicationStrategy() { @@ -40,7 +40,7 @@ public class EventListenerGroupAppendListenerTest extends BaseCoreFunctionalTest } @Override - public DuplicationStrategy.Action getAction() { + public Action getAction() { return Action.REPLACE_ORIGINAL; } }; @@ -60,8 +60,9 @@ public class EventListenerGroupAppendListenerTest extends BaseCoreFunctionalTest } private void runAppendListenerTest( - DuplicationStrategy duplicationStrategy, DefaultMergeEventListener mergeEventListener) { - doInHibernate( this::sessionFactory, session -> { + DuplicationStrategy duplicationStrategy, + DefaultMergeEventListener mergeEventListener) { + inTransaction( session -> { ServiceRegistryImplementor serviceRegistry = sessionFactory().getServiceRegistry(); EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); @@ -72,7 +73,7 @@ public class EventListenerGroupAppendListenerTest extends BaseCoreFunctionalTest group.appendListener( mergeEventListener ); Iterable listeners = group.listeners(); - assertTrue( "Should have at least one listener", listeners.iterator().hasNext() ); + assertTrue( listeners.iterator().hasNext(), "Should have at least one listener" ); listeners.forEach( this::assertCallbackRegistry ); } ); } @@ -80,7 +81,7 @@ public class EventListenerGroupAppendListenerTest extends BaseCoreFunctionalTest private void assertCallbackRegistry( MergeEventListener listener) { try { - assertNotNull( "callbackRegistry should not be null", getCallbackRegistry( listener ) ); + assertNotNull( getCallbackRegistry( listener ), "callbackRegistry should not be null" ); } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { fail( "Unable to get callbackRegistry field on listener" ); diff --git a/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java b/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java index c27d7fe3f3..547c5a55c2 100644 --- a/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java +++ b/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java @@ -27,22 +27,36 @@ import org.hibernate.Transaction; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** * @author Artem K. * @author Nathan Xu */ -@TestForIssue( jiraKey = "HHH-14178" ) -@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) -public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunctionalTestCase { +@TestForIssue(jiraKey = "HHH-14178") +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@DomainModel( + annotatedClasses = { + NewlyInstantiatdCollectionSkipDeleteOrphanTest.VersionedParent.class, + NewlyInstantiatdCollectionSkipDeleteOrphanTest.UnversionedParent.class, + NewlyInstantiatdCollectionSkipDeleteOrphanTest.Child.class, + NewlyInstantiatdCollectionSkipDeleteOrphanTest.VersionedMappingUnversionedParent.class, + NewlyInstantiatdCollectionSkipDeleteOrphanTest.VersionedMappingVersionedParent.class + } +) +@SessionFactory +public class NewlyInstantiatdCollectionSkipDeleteOrphanTest { private UnversionedParent up; private VersionedParent vp; @@ -50,18 +64,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc private VersionedMappingUnversionedParent vmup; private VersionedMappingVersionedParent vmvp; - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - VersionedParent.class, - UnversionedParent.class, - Child.class, - VersionedMappingUnversionedParent.class, - VersionedMappingVersionedParent.class - }; - } - - @Before + @BeforeEach public void setup() { up = new UnversionedParent(); @@ -78,24 +81,24 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc } - @After - public void cleanup() { - inTransaction( s -> { - if (up.getId() != null) { + @AfterEach + public void cleanup(SessionFactoryScope scope) { + scope.inTransaction( s -> { + if ( up.getId() != null ) { s.delete( up ); } - if (vp.getId() != null) { + if ( vp.getId() != null ) { s.delete( vp ); } - if (c.getId() != null) { + if ( c.getId() != null ) { s.delete( c ); } } ); } @Test - public void VersionedMappingVersionedParentSaveUpdate() { - inSession( s -> { + public void VersionedMappingVersionedParentSaveUpdate(SessionFactoryScope scope) { + scope.inSession( s -> { s.setHibernateFlushMode( FlushMode.MANUAL ); Transaction trx = s.beginTransaction(); @@ -105,27 +108,28 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc // Persist Child associated with versioned parent s.saveOrUpdate( c ); - Assert.assertNotEquals( Integer.valueOf(0), c.getId() ); + assertNotEquals( Integer.valueOf( 0 ), c.getId() ); // Persist VersionParent s.saveOrUpdate( vp ); - Assert.assertNotEquals( Integer.valueOf(0), vp.getId() ); + assertNotEquals( Integer.valueOf( 0 ), vp.getId() ); // Persist versioned mapping now that parent id is generated s.saveOrUpdate( vmvp ); - Assert.assertNotNull( vmvp.getId() ); - Assert.assertNotEquals( Integer.valueOf(0), vmvp.getId().getParentId() ); - Assert.assertNotEquals( Integer.valueOf(0), vmvp.getId().getChildId() ); + assertNotNull( vmvp.getId() ); + assertNotEquals( Integer.valueOf( 0 ), vmvp.getId().getParentId() ); + assertNotEquals( Integer.valueOf( 0 ), vmvp.getId().getChildId() ); s.flush(); trx.commit(); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { // Transaction is rolled back so we do not want delete code in cleanup to execute. // Reset any possible ID assignments vp.setId( null ); c.setId( null ); - if (trx.isActive()) { + if ( trx.isActive() ) { trx.rollback(); } throw e; @@ -134,8 +138,8 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc } @Test - public void VersionedMappingUnversionedParentSaveUpdate() { - inSession( s -> { + public void VersionedMappingUnversionedParentSaveUpdate(SessionFactoryScope scope) { + scope.inSession( s -> { s.setHibernateFlushMode( FlushMode.MANUAL ); Transaction trx = s.beginTransaction(); @@ -145,27 +149,28 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc // Persist child associated with versioned mapping of unversioned parent s.saveOrUpdate( c ); - Assert.assertNotEquals( Integer.valueOf(0), c.getId() ); + assertNotEquals( Integer.valueOf( 0 ), c.getId() ); // Persist unversioned parent s.saveOrUpdate( up ); - Assert.assertNotEquals( Integer.valueOf(0), up.getId() ); + assertNotEquals( Integer.valueOf( 0 ), up.getId() ); // Persist versioned mapping s.saveOrUpdate( vmup ); - Assert.assertNotNull( vmup.getId() ); - Assert.assertNotEquals( Integer.valueOf(0), vmup.getId().getParentId() ); - Assert.assertNotEquals( Integer.valueOf(0), vmup.getId().getChildId() ); + assertNotNull( vmup.getId() ); + assertNotEquals( Integer.valueOf( 0 ), vmup.getId().getParentId() ); + assertNotEquals( Integer.valueOf( 0 ), vmup.getId().getChildId() ); s.flush(); trx.commit(); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { // Transaction is rolled back so we do not want delete code in cleanup to execute. // Reset any possible ID assignments up.setId( null ); c.setId( null ); - if (trx.isActive()) { + if ( trx.isActive() ) { trx.rollback(); } throw e; @@ -236,7 +241,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc private Integer parentId; private Integer childId; - @Column(name="ParentId", nullable=false) + @Column(name = "ParentId", nullable = false) public Integer getParentId() { return parentId; } @@ -245,7 +250,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc this.parentId = parentId; } - @Column(name="ChildId", nullable=false) + @Column(name = "ChildId", nullable = false) public Integer getChildId() { return childId; } @@ -256,19 +261,22 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Override public int hashCode() { - return Objects.hash(getParentId(), getChildId()); + return Objects.hash( getParentId(), getChildId() ); } @Override public boolean equals(Object obj) { - if (this == obj) { + if ( this == obj ) { return true; } - if (!(obj instanceof MappingId)) { + if ( !( obj instanceof MappingId ) ) { return false; } MappingId other = (MappingId) obj; - return Objects.equals(getParentId(), other.getParentId()) && Objects.equals(getChildId(), other.getChildId()); + return Objects.equals( getParentId(), other.getParentId() ) && Objects.equals( + getChildId(), + other.getChildId() + ); } @Override @@ -288,21 +296,21 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="Id", nullable=false) + @Column(name = "Id", nullable = false) public Integer getId() { return id; } public void setId(Integer id) { - if (!Objects.equals(id, getId())) { + if ( !Objects.equals( id, getId() ) ) { this.id = id; - getVersionedMappings().forEach(c -> { - if (c.getId() == null) { - c.setId(new MappingId()); + getVersionedMappings().forEach( c -> { + if ( c.getId() == null ) { + c.setId( new MappingId() ); } - c.getId().setParentId(id); - }); + c.getId().setParentId( id ); + } ); } } @@ -314,38 +322,48 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc this.name = name; } - @OneToMany(mappedBy="parent", cascade={ javax.persistence.CascadeType.DETACH, javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.REFRESH, javax.persistence.CascadeType.REMOVE }, orphanRemoval=true) - @Cascade({ org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.LOCK, org.hibernate.annotations.CascadeType.REPLICATE }) + @OneToMany(mappedBy = "parent", cascade = { + javax.persistence.CascadeType.DETACH, + javax.persistence.CascadeType.MERGE, + javax.persistence.CascadeType.REFRESH, + javax.persistence.CascadeType.REMOVE + }, orphanRemoval = true) + @Cascade({ + org.hibernate.annotations.CascadeType.DELETE, + org.hibernate.annotations.CascadeType.LOCK, + org.hibernate.annotations.CascadeType.REPLICATE + }) protected Set getVersionedMappings() { - if (versionedMappings == null) { + if ( versionedMappings == null ) { versionedMappings = new HashSet<>(); } return this.versionedMappings; } protected void setVersionedMappings(Set value) { - if (value == null && this.versionedMappings != null) { + if ( value == null && this.versionedMappings != null ) { this.versionedMappings.clear(); - } else { + } + else { this.versionedMappings = value; } } @Transient public Collection getVersionedMappingsCollection() { - return new ArrayList<>(getVersionedMappings()); + return new ArrayList<>( getVersionedMappings() ); } public void addVersionedMappings(VersionedMappingUnversionedParent addValue) { - if (addValue != null && !this.getVersionedMappings().contains(addValue)) { - this.versionedMappings.add(addValue); - addValue.addParent(this); + if ( addValue != null && !this.getVersionedMappings().contains( addValue ) ) { + this.versionedMappings.add( addValue ); + addValue.addParent( this ); } } public void removeVersionedMappings(VersionedMappingUnversionedParent removeValue) { - if (this.versionedMappings != null && this.versionedMappings.contains(removeValue)) { - this.versionedMappings.remove(removeValue); + if ( this.versionedMappings != null && this.versionedMappings.contains( removeValue ) ) { + this.versionedMappings.remove( removeValue ); removeValue.removeParent(); } } @@ -357,14 +375,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Override public boolean equals(Object obj) { - if (this == obj) { + if ( this == obj ) { return true; } - if (!(obj instanceof UnversionedParent)) { + if ( !( obj instanceof UnversionedParent ) ) { return false; } UnversionedParent other = (UnversionedParent) obj; - return Objects.equals(getId(), other.getId()); + return Objects.equals( getId(), other.getId() ); } } @@ -379,21 +397,21 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="Id", nullable=false) + @Column(name = "Id", nullable = false) public Integer getId() { return id; } public void setId(Integer id) { - if (!Objects.equals(id, getId())) { + if ( !Objects.equals( id, getId() ) ) { this.id = id; - getChildren().forEach(c -> { - if (c.getId() == null) { - c.setId(new MappingId()); + getChildren().forEach( c -> { + if ( c.getId() == null ) { + c.setId( new MappingId() ); } - c.getId().setParentId(id); - }); + c.getId().setParentId( id ); + } ); } } @@ -406,7 +424,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc } @Version - @Column(name="Version", nullable=false) + @Column(name = "Version", nullable = false) public Long getVersion() { return version; } @@ -415,38 +433,48 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc this.version = version; } - @OneToMany(mappedBy="parent", cascade={ javax.persistence.CascadeType.DETACH, javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.REFRESH, javax.persistence.CascadeType.REMOVE }, orphanRemoval=true) - @Cascade({ org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.LOCK, org.hibernate.annotations.CascadeType.REPLICATE }) + @OneToMany(mappedBy = "parent", cascade = { + javax.persistence.CascadeType.DETACH, + javax.persistence.CascadeType.MERGE, + javax.persistence.CascadeType.REFRESH, + javax.persistence.CascadeType.REMOVE + }, orphanRemoval = true) + @Cascade({ + org.hibernate.annotations.CascadeType.DELETE, + org.hibernate.annotations.CascadeType.LOCK, + org.hibernate.annotations.CascadeType.REPLICATE + }) protected Set getChildren() { - if (children == null) { + if ( children == null ) { children = new HashSet<>(); } return this.children; } protected void setChildren(Set value) { - if (value == null && this.children != null) { + if ( value == null && this.children != null ) { this.children.clear(); - } else { + } + else { this.children = value; } } @Transient public Collection getChildrenCollection() { - return new ArrayList<>(getChildren()); + return new ArrayList<>( getChildren() ); } public void addChild(VersionedMappingVersionedParent addValue) { - if (addValue != null && !this.getChildren().contains(addValue)) { - this.children.add(addValue); - addValue.addParent(this); + if ( addValue != null && !this.getChildren().contains( addValue ) ) { + this.children.add( addValue ); + addValue.addParent( this ); } } public void removeChild(VersionedMappingVersionedParent removeValue) { - if (this.children != null && this.children.contains(removeValue)) { - this.children.remove(removeValue); + if ( this.children != null && this.children.contains( removeValue ) ) { + this.children.remove( removeValue ); removeValue.removeParent(); } } @@ -458,14 +486,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Override public boolean equals(Object obj) { - if (this == obj) { + if ( this == obj ) { return true; } - if (!(obj instanceof VersionedParent)) { + if ( !( obj instanceof VersionedParent ) ) { return false; } VersionedParent other = (VersionedParent) obj; - return Objects.equals(getId(), other.getId()); + return Objects.equals( getId(), other.getId() ); } } @@ -488,7 +516,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc } @Version - @Column(name="Version", nullable=false) + @Column(name = "Version", nullable = false) public Long getVersion() { return version; } @@ -507,9 +535,9 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc protected UnversionedParent parent; - @ManyToOne(optional=false, fetch=FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.LAZY) @MapsId("parentId") - @JoinColumn(name="ParentId", nullable=false) + @JoinColumn(name = "ParentId", nullable = false) public UnversionedParent getParent() { return this.parent; } @@ -520,30 +548,30 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc public void addParent(UnversionedParent value) { UnversionedParent oldParent = getParent(); - if (!Objects.equals(value, oldParent)) { - if (oldParent != null) { - setParent(null); - oldParent.removeVersionedMappings(this); + if ( !Objects.equals( value, oldParent ) ) { + if ( oldParent != null ) { + setParent( null ); + oldParent.removeVersionedMappings( this ); } - if (value != null) { - setParent(value); - if (getId() == null) { - setId(new MappingId()); + if ( value != null ) { + setParent( value ); + if ( getId() == null ) { + setId( new MappingId() ); } - getId().setParentId(value.getId()); - value.addVersionedMappings(this); + getId().setParentId( value.getId() ); + value.addVersionedMappings( this ); } } } public void removeParent() { - addParent(null); + addParent( null ); } - @ManyToOne(optional=false, fetch=FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.LAZY) @MapsId("childId") - @JoinColumn(name="ChildId", nullable=false) + @JoinColumn(name = "ChildId", nullable = false) public Child getChild() { return child; } @@ -554,23 +582,23 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc public void addChild(Child value) { Child oldChild = getChild(); - if (!Objects.equals(value, oldChild)) { - if (oldChild != null) { - setChild(null); + if ( !Objects.equals( value, oldChild ) ) { + if ( oldChild != null ) { + setChild( null ); } - if (value != null) { - setChild(value); - if (getId() == null) { - setId(new MappingId()); + if ( value != null ) { + setChild( value ); + if ( getId() == null ) { + setId( new MappingId() ); } - getId().setChildId(value.getId()); + getId().setChildId( value.getId() ); } } } public void removeChild() { - addChild(null); + addChild( null ); } @Override @@ -580,14 +608,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Override public boolean equals(Object obj) { - if (this == obj) { + if ( this == obj ) { return true; } - if (!(obj instanceof VersionedMappingUnversionedParent)) { + if ( !( obj instanceof VersionedMappingUnversionedParent ) ) { return false; } VersionedMappingUnversionedParent other = (VersionedMappingUnversionedParent) obj; - return Objects.equals(getId(), other.getId()); + return Objects.equals( getId(), other.getId() ); } } @@ -610,7 +638,7 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc } @Version - @Column(name="Version", nullable=false) + @Column(name = "Version", nullable = false) public Long getVersion() { return version; } @@ -629,9 +657,9 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc protected VersionedParent parent; - @ManyToOne(optional=false, fetch=FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.LAZY) @MapsId("parentId") - @JoinColumn(name="ParentId", nullable=false) + @JoinColumn(name = "ParentId", nullable = false) public VersionedParent getParent() { return this.parent; } @@ -642,30 +670,30 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc public void addParent(VersionedParent value) { VersionedParent oldParent = getParent(); - if (!Objects.equals(value, oldParent)) { - if (oldParent != null) { - setParent(null); - oldParent.removeChild(this); + if ( !Objects.equals( value, oldParent ) ) { + if ( oldParent != null ) { + setParent( null ); + oldParent.removeChild( this ); } - if (value != null) { - setParent(value); - if (getId() == null) { - setId(new MappingId()); + if ( value != null ) { + setParent( value ); + if ( getId() == null ) { + setId( new MappingId() ); } - getId().setParentId(value.getId()); - value.addChild(this); + getId().setParentId( value.getId() ); + value.addChild( this ); } } } public void removeParent() { - addParent(null); + addParent( null ); } - @ManyToOne(optional=false, fetch=FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.LAZY) @MapsId("childId") - @JoinColumn(name="ChildId", nullable=false) + @JoinColumn(name = "ChildId", nullable = false) public Child getChild() { return child; } @@ -676,23 +704,23 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc public void addChild(Child value) { Child oldChild = getChild(); - if (!Objects.equals(value, oldChild)) { - if (oldChild != null) { - setChild(null); + if ( !Objects.equals( value, oldChild ) ) { + if ( oldChild != null ) { + setChild( null ); } - if (value != null) { - setChild(value); - if (getId() == null) { - setId(new MappingId()); + if ( value != null ) { + setChild( value ); + if ( getId() == null ) { + setId( new MappingId() ); } - getId().setChildId(value.getId()); + getId().setChildId( value.getId() ); } } } public void removeChild() { - addChild(null); + addChild( null ); } @Override @@ -702,14 +730,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc @Override public boolean equals(Object obj) { - if (this == obj) { + if ( this == obj ) { return true; } - if (!(obj instanceof VersionedMappingVersionedParent)) { + if ( !( obj instanceof VersionedMappingVersionedParent ) ) { return false; } VersionedMappingVersionedParent other = (VersionedMappingVersionedParent) obj; - return Objects.equals(getId(), other.getId()); + return Objects.equals( getId(), other.getId() ); } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingBatchObserver.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingBatchObserver.java index 92bbf3b0fd..5ee2d9ea05 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingBatchObserver.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingBatchObserver.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.common; +package org.hibernate.orm.test.common; import org.hibernate.engine.jdbc.batch.spi.BatchObserver; diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingConnectionObserver.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingConnectionObserver.java index 009c98b393..809c8f4c41 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingConnectionObserver.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingConnectionObserver.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.common; +package org.hibernate.orm.test.common; import java.sql.Connection; diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingTransactionObserver.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingTransactionObserver.java index 93f7cf4751..6b653dcbd0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/JournalingTransactionObserver.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/common/JournalingTransactionObserver.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.common; +package org.hibernate.orm.test.common; import org.hibernate.engine.transaction.spi.TransactionObserver; diff --git a/hibernate-core/src/test/java/org/hibernate/event/EmbeddableCallbackTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/event/EmbeddableCallbackTest.java similarity index 54% rename from hibernate-core/src/test/java/org/hibernate/event/EmbeddableCallbackTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/event/EmbeddableCallbackTest.java index ad2be1ffac..b801a40ed3 100644 --- a/hibernate-core/src/test/java/org/hibernate/event/EmbeddableCallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/event/EmbeddableCallbackTest.java @@ -4,36 +4,43 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.event; +package org.hibernate.orm.test.event; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.PrePersist; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - import org.hibernate.testing.TestForIssue; -import org.junit.Test; +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.Test; -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; /** * @author Vlad Mihalcea */ -public class EmbeddableCallbackTest extends BaseEntityManagerFunctionalTestCase { +@Jpa( + annotatedClasses = EmbeddableCallbackTest.Employee.class +) +public class EmbeddableCallbackTest { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Employee.class }; + @AfterEach + public void tearDown(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> + entityManager.createQuery( "delete from Employee" ).executeUpdate() + ); } @Test @TestForIssue(jiraKey = "HHH-12326") - public void test() { - doInJPA( this::entityManagerFactory, entityManager -> { + public void test(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { Employee employee = new Employee(); employee.details = new EmployeeDetails(); employee.id = 1; @@ -41,28 +48,28 @@ public class EmbeddableCallbackTest extends BaseEntityManagerFunctionalTestCase entityManager.persist( employee ); } ); - doInJPA( this::entityManagerFactory, entityManager -> { + scope.inTransaction( entityManager -> { Employee employee = entityManager.find( Employee.class, 1 ); - assertEquals( "Vlad", employee.name ); - assertEquals( "Developer Advocate", employee.details.jobTitle ); + assertThat( employee.name, is( "Vlad" ) ); + assertThat( employee.details.jobTitle, is( "Developer Advocate" ) ); } ); } @Test @TestForIssue(jiraKey = "HHH-13110") - public void testNullEmbeddable() { - doInJPA( this::entityManagerFactory, entityManager -> { + public void testNullEmbeddable(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { Employee employee = new Employee(); employee.id = 1; entityManager.persist( employee ); } ); - doInJPA( this::entityManagerFactory, entityManager -> { + scope.inTransaction( entityManager -> { Employee employee = entityManager.find( Employee.class, 1 ); - assertEquals( "Vlad", employee.name ); + assertThat( employee.name, is( "Vlad" ) ); assertNull( employee.details ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/BatchingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/BatchingTest.java index 46ea00a993..5ed52f044d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/BatchingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/BatchingTest.java @@ -25,7 +25,7 @@ import org.hibernate.jdbc.Expectations; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.test.common.JournalingBatchObserver; +import org.hibernate.orm.test.common.JournalingBatchObserver; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java similarity index 57% rename from hibernate-core/src/test/java/org/hibernate/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java index 23639cd9c6..f68bcd17af 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/lazydetachedpersist/LazyPersistWithDetachedAssociationTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.lazydetachedpersist; +package org.hibernate.orm.test.lazydetachedpersist; import javax.persistence.Basic; import javax.persistence.Entity; @@ -13,39 +13,35 @@ import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.Table; -import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Before; -import org.junit.Test; +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; -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; -public class LazyPersistWithDetachedAssociationTest - extends BaseCoreFunctionalTestCase { +@DomainModel( + annotatedClasses = { + LazyPersistWithDetachedAssociationTest.Address.class, + LazyPersistWithDetachedAssociationTest.Person.class, + } +) +@SessionFactory +@ServiceRegistry( + settings = { @Setting(name = Environment.ENABLE_LAZY_LOAD_NO_TRANS, value = "false") } +) +public class LazyPersistWithDetachedAssociationTest { - - @Override - protected void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "false" ); - cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Address.class, - Person.class, - }; - } - - @Before - public void setUpData() { - doInHibernate( this::sessionFactory, session -> { + @BeforeEach + public void setUpData(SessionFactoryScope scope) { + scope.inTransaction( session -> { Address address = new Address(); address.setId( 1L ); address.setContent( "21 Jump St" ); @@ -53,18 +49,20 @@ public class LazyPersistWithDetachedAssociationTest } ); } - @Override - protected boolean isCleanupTestDataRequired() { - return true; + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from Person" ).executeUpdate(); + session.createQuery( "delete from Address" ).executeUpdate(); + } + ); } @Test @TestForIssue(jiraKey = "HHH-3846") - public void testDetachedAssociationOnPersisting() { - sessionFactory().getStatistics().clear(); - - Address loadedAddress = doInHibernate( - this::sessionFactory, + public void testDetachedAssociationOnPersisting(SessionFactoryScope scope) { + Address loadedAddress = scope.fromTransaction( session -> { // first load the address Address _loadedAddress = session.load( @@ -76,7 +74,7 @@ public class LazyPersistWithDetachedAssociationTest } ); - doInHibernate( this::sessionFactory, session -> { + scope.inTransaction( session -> { session.get( Address.class, 1L ); Person person = new Person(); @@ -88,7 +86,7 @@ public class LazyPersistWithDetachedAssociationTest } ); } - @Entity + @Entity(name = "Address") @Table(name = "eg_sbt_address") public static class Address { @@ -114,7 +112,7 @@ public class LazyPersistWithDetachedAssociationTest } } - @Entity + @Entity(name = "Person") @Table(name = "eg_sbt_person") public static class Person { @@ -131,7 +129,7 @@ public class LazyPersistWithDetachedAssociationTest this.id = id; } - @ManyToOne(fetch = FetchType.LAZY, cascade = {}) + @ManyToOne(fetch = FetchType.LAZY) public Address getAddress() { return address; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java new file mode 100644 index 0000000000..5e39becaa5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java @@ -0,0 +1,255 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.manytomanyassociationclass; + +import java.util.HashSet; + +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +/** + * Abstract class for tests on many-to-many association using an association class. + * + * @author Gail Badner + */ +@SessionFactory +public abstract class AbstractManyToManyAssociationClassTest { + private User user; + private Group group; + private Membership membership; + + public abstract Membership createMembership(String name); + + @BeforeEach + protected void prepareTest(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + user = new User( "user" ); + group = new Group( "group" ); + session.save( user ); + session.save( group ); + membership = createMembership( "membership" ); + addMembership( user, group, membership ); + } + ); + } + + @AfterEach + protected void cleanupTest(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from " + membership.getClass().getName() ); + session.createQuery( "delete from User" ); + session.createQuery( "delete from Group" ); + } + ); + } + + public User getUser() { + return user; + } + + public Group getGroup() { + return group; + } + + public Membership getMembership() { + return membership; + } + + @Test + public void testRemoveAndAddSameElement(SessionFactoryScope scope) { + deleteMembership( user, group, membership ); + addMembership( user, group, membership ); + + scope.inTransaction( + session -> + session.merge( user ) + ); + + scope.inTransaction( + session -> { + user = session.get( User.class, user.getId() ); + group = session.get( Group.class, group.getId() ); + membership = session.get( membership.getClass(), membership.getId() ); + assertEquals( "user", user.getName() ); + assertEquals( "group", group.getName() ); + assertEquals( "membership", membership.getName() ); + assertEquals( 1, user.getMemberships().size() ); + assertEquals( 1, group.getMemberships().size() ); + assertSame( membership, user.getMemberships().iterator().next() ); + assertSame( membership, group.getMemberships().iterator().next() ); + assertSame( user, membership.getUser() ); + assertSame( group, membership.getGroup() ); + } + ); + } + + @Test + public void testRemoveAndAddEqualElement(SessionFactoryScope scope) { + deleteMembership( user, group, membership ); + membership = createMembership( "membership" ); + addMembership( user, group, membership ); + + scope.inTransaction( + session -> + session.merge( user ) + ); + + scope.inTransaction( + session -> { + user = session.get( User.class, user.getId() ); + group = session.get( Group.class, group.getId() ); + membership = session.get( membership.getClass(), membership.getId() ); + assertEquals( "user", user.getName() ); + assertEquals( "group", group.getName() ); + assertEquals( "membership", membership.getName() ); + assertEquals( 1, user.getMemberships().size() ); + assertEquals( 1, group.getMemberships().size() ); + assertSame( membership, user.getMemberships().iterator().next() ); + assertSame( membership, group.getMemberships().iterator().next() ); + assertSame( user, membership.getUser() ); + assertSame( group, membership.getGroup() ); + } + ); + } + + @Test + public void testRemoveAndAddEqualCollection(SessionFactoryScope scope) { + deleteMembership( user, group, membership ); + membership = createMembership( "membership" ); + user.setMemberships( new HashSet() ); + group.setMemberships( new HashSet() ); + addMembership( user, group, membership ); + + scope.inTransaction( + session -> + session.merge( user ) + ); + + scope.inTransaction( + session -> { + user = session.get( User.class, user.getId() ); + group = session.get( Group.class, group.getId() ); + membership = session.get( membership.getClass(), membership.getId() ); + assertEquals( "user", user.getName() ); + assertEquals( "group", group.getName() ); + assertEquals( "membership", membership.getName() ); + assertEquals( 1, user.getMemberships().size() ); + assertEquals( 1, group.getMemberships().size() ); + assertSame( membership, user.getMemberships().iterator().next() ); + assertSame( membership, group.getMemberships().iterator().next() ); + assertSame( user, membership.getUser() ); + assertSame( group, membership.getGroup() ); + } + ); + } + + @Test + public void testRemoveAndAddSameElementNonKeyModified(SessionFactoryScope scope) { + deleteMembership( user, group, membership ); + addMembership( user, group, membership ); + membership.setName( "membership1" ); + + scope.inTransaction( + session -> + session.merge( user ) + ); + + scope.inTransaction( + session -> { + user = session.get( User.class, user.getId() ); + group = session.get( Group.class, group.getId() ); + membership = session.get( membership.getClass(), membership.getId() ); + assertEquals( "user", user.getName() ); + assertEquals( "group", group.getName() ); + assertEquals( "membership1", membership.getName() ); + assertEquals( 1, user.getMemberships().size() ); + assertEquals( 1, group.getMemberships().size() ); + assertSame( membership, user.getMemberships().iterator().next() ); + assertSame( membership, group.getMemberships().iterator().next() ); + assertSame( user, membership.getUser() ); + assertSame( group, membership.getGroup() ); + } + ); + } + + @Test + public void testRemoveAndAddEqualElementNonKeyModified(SessionFactoryScope scope) { + deleteMembership( user, group, membership ); + membership = createMembership( "membership" ); + addMembership( user, group, membership ); + membership.setName( "membership1" ); + + scope.inTransaction( + session -> + session.merge( user ) + ); + + scope.inTransaction( + session -> { + user = session.get( User.class, user.getId() ); + group = session.get( Group.class, group.getId() ); + membership = session.get( membership.getClass(), membership.getId() ); + assertEquals( "user", user.getName() ); + assertEquals( "group", group.getName() ); + assertEquals( "membership1", membership.getName() ); + assertEquals( 1, user.getMemberships().size() ); + assertEquals( 1, group.getMemberships().size() ); + assertSame( membership, user.getMemberships().iterator().next() ); + assertSame( membership, group.getMemberships().iterator().next() ); + assertSame( user, membership.getUser() ); + assertSame( group, membership.getGroup() ); + } + ); + } + + @Test + public void testDeleteDetached(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.delete( user ); + session.delete( group ); + } + ); + + scope.inTransaction( + session -> { + assertNull( session.get( User.class, user.getId() ) ); + assertNull( session.get( Group.class, group.getId() ) ); + assertNull( session.get( membership.getClass(), membership.getId() ) ); + } + ); + } + + public void deleteMembership(User u, Group g, Membership ug) { + if ( u == null || g == null ) { + throw new IllegalArgumentException(); + } + u.getMemberships().remove( ug ); + g.getMemberships().remove( ug ); + ug.setUser( null ); + ug.setGroup( null ); + } + + public void addMembership(User u, Group g, Membership ug) { + if ( u == null || g == null ) { + throw new IllegalArgumentException(); + } + ug.setUser( u ); + ug.setGroup( g ); + u.getMemberships().add( ug ); + g.getMemberships().add( ug ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Group.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Group.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Group.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Group.java index fb2a2a342b..cb2765db4d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Group.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Group.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass; +package org.hibernate.orm.test.manytomanyassociationclass; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Membership.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Membership.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Membership.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Membership.java index 0b737fc730..66cc057588 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/Membership.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/Membership.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass; +package org.hibernate.orm.test.manytomanyassociationclass; import java.io.Serializable; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/User.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/User.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/User.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/User.java index 0b698f8065..0e48b2d726 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/User.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/User.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass; +package org.hibernate.orm.test.manytomanyassociationclass; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java similarity index 55% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java index df6c9fc355..64ec368266 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/ManyToManyAssociationClassCompositeIdTest.java @@ -4,12 +4,13 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass.compositeid; +package org.hibernate.orm.test.manytomanyassociationclass.compositeid; -import org.hibernate.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; -import org.hibernate.test.manytomanyassociationclass.Group; -import org.hibernate.test.manytomanyassociationclass.Membership; -import org.hibernate.test.manytomanyassociationclass.User; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.orm.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; +import org.hibernate.orm.test.manytomanyassociationclass.Group; +import org.hibernate.orm.test.manytomanyassociationclass.Membership; +import org.hibernate.orm.test.manytomanyassociationclass.User; /** * Tests on many-to-many association using an association class with a composite ID containing @@ -17,17 +18,16 @@ import org.hibernate.test.manytomanyassociationclass.User; * * @author Gail Badner */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml" +) public class ManyToManyAssociationClassCompositeIdTest extends AbstractManyToManyAssociationClassTest { - @Override - public String[] getMappings() { - return new String[] { "manytomanyassociationclass/compositeid/Mappings.hbm.xml" }; - } @Override - public Membership createMembership( String name ) { + public Membership createMembership(String name) { return new MembershipWithCompositeId( name ); } - + @Override public void deleteMembership(User u, Group g, Membership ug) { if ( u == null || g == null ) { @@ -35,7 +35,7 @@ public class ManyToManyAssociationClassCompositeIdTest extends AbstractManyToMan } u.getMemberships().remove( ug ); g.getMemberships().remove( ug ); - ug.setId(null); + ug.setId( null ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml similarity index 83% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml index 28a17ffd4e..9683be01af 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/Mappings.hbm.xml @@ -7,9 +7,9 @@ --> - + - + @@ -20,7 +20,7 @@ - + @@ -38,9 +38,9 @@ - - diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java index efbb4a46db..a7c35a188e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/compositeid/MembershipWithCompositeId.java @@ -4,12 +4,12 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass.compositeid; +package org.hibernate.orm.test.manytomanyassociationclass.compositeid; import java.io.Serializable; -import org.hibernate.test.manytomanyassociationclass.Group; -import org.hibernate.test.manytomanyassociationclass.Membership; -import org.hibernate.test.manytomanyassociationclass.User; +import org.hibernate.orm.test.manytomanyassociationclass.Group; +import org.hibernate.orm.test.manytomanyassociationclass.Membership; +import org.hibernate.orm.test.manytomanyassociationclass.User; /** * Models a user's membership in a group. diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java index 1c4c2d374d..96d71ddf37 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/ManyToManyAssociationClassAssignedIdTest.java @@ -4,22 +4,21 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.manytomanyassociationclass.surrogateid.assigned; +package org.hibernate.orm.test.manytomanyassociationclass.surrogateid.assigned; -import org.hibernate.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; -import org.hibernate.test.manytomanyassociationclass.Membership; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.orm.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; +import org.hibernate.orm.test.manytomanyassociationclass.Membership; /** * Tests on many-to-many association using an association class with a surrogate ID that is assigned. * * @author Gail Badner */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml" +) public class ManyToManyAssociationClassAssignedIdTest extends AbstractManyToManyAssociationClassTest { - @Override - public String[] getMappings() { - return new String[] { "manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml" }; - } - @Override public Membership createMembership(String name) { return new Membership( Long.valueOf( 1000 ), name ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml index 6210ce6a84..8d69ff1c7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/assigned/Mappings.hbm.xml @@ -7,7 +7,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java new file mode 100644 index 0000000000..740033fc3d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java @@ -0,0 +1,121 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.manytomanyassociationclass.surrogateid.generated; + +import java.util.HashSet; +import javax.persistence.PersistenceException; + +import org.hibernate.exception.ConstraintViolationException; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.orm.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; +import org.hibernate.orm.test.manytomanyassociationclass.Membership; +import org.junit.jupiter.api.Test; + +import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * Tests on many-to-many association using an association class with a surrogate ID that is generated. + * + * @author Gail Badner + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml" +) +public class ManyToManyAssociationClassGeneratedIdTest extends AbstractManyToManyAssociationClassTest { + @Override + public Membership createMembership(String name) { + return new Membership( name ); + } + + @Test + public void testRemoveAndAddEqualElement(SessionFactoryScope scope) { + deleteMembership( getUser(), getGroup(), getMembership() ); + addMembership( getUser(), getGroup(), createMembership( "membership" ) ); + + scope.inSession( + session -> { + try { + session.getTransaction().begin(); + // The new membership is transient (it has a null surrogate ID), so + // Hibernate assumes that it should be added to the collection. + // Inserts are done before deletes, so a ConstraintViolationException + // will be thrown on the insert because the unique constraint on the + // user and group IDs in the join table is violated. See HHH-2801. + session.merge( getUser() ); + session.getTransaction().commit(); + fail( "should have failed because inserts are before deletes" ); + } + catch (Exception e) { + session.getTransaction().rollback(); + // expected + assertTyping( ConstraintViolationException.class, e.getCause() ); + } + } + ); + } + + @Test + public void testRemoveAndAddEqualCollection(SessionFactoryScope scope) { + deleteMembership( getUser(), getGroup(), getMembership() ); + getUser().setMemberships( new HashSet() ); + getGroup().setMemberships( new HashSet() ); + addMembership( getUser(), getGroup(), createMembership( "membership" ) ); + + scope.inSession( + session -> { + try { + session.getTransaction().begin(); + // The new membership is transient (it has a null surrogate ID), so + // Hibernate assumes that it should be added to the collection. + // Inserts are done before deletes, so a ConstraintViolationException + // will be thrown on the insert because the unique constraint on the + // user and group IDs in the join table is violated. See HHH-2801. + session.merge( getUser() ); + session.getTransaction().commit(); + fail( "should have failed because inserts are before deletes" ); + } + catch (PersistenceException e) { + session.getTransaction().rollback(); + // expected + assertTyping( ConstraintViolationException.class, e.getCause() ); + } + } + ); + } + + @Test + public void testRemoveAndAddEqualElementNonKeyModified(SessionFactoryScope scope) { + deleteMembership( getUser(), getGroup(), getMembership() ); + Membership membershipNew = createMembership( "membership" ); + addMembership( getUser(), getGroup(), membershipNew ); + membershipNew.setName( "membership1" ); + + scope.inSession( + session -> { + try { + session.getTransaction().begin(); + // The new membership is transient (it has a null surrogate ID), so + // Hibernate assumes that it should be added to the collection. + // Inserts are done before deletes, so a ConstraintViolationException + // will be thrown on the insert because the unique constraint on the + // user and group IDs in the join table is violated. See HHH-2801. + session.merge( getUser() ); + session.getTransaction().commit(); + fail( "should have failed because inserts are before deletes" ); + } + catch (PersistenceException e) { + session.getTransaction().rollback(); + // expected + assertTyping( ConstraintViolationException.class, e.getCause() ); + } + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml index d37bfd1cab..e50d61c740 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml @@ -7,7 +7,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Address.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Address.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/Address.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Address.java index fb3b6c7b26..5924076ea3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Address.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Address.java @@ -6,7 +6,7 @@ */ //$Id: Address.java 7119 2005-06-12 22:03:30Z oneovthafew $ -package org.hibernate.test.ondelete; +package org.hibernate.orm.test.ondelete; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Employee.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Employee.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/Employee.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Employee.java index 657a754e65..ae0471f54b 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Employee.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Employee.java @@ -6,7 +6,7 @@ */ //$Id: Employee.java 7119 2005-06-12 22:03:30Z oneovthafew $ -package org.hibernate.test.ondelete; +package org.hibernate.orm.test.ondelete; import java.math.BigDecimal; /** diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/OnDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/OnDeleteTest.java new file mode 100755 index 0000000000..6b9cf13af1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/OnDeleteTest.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ondelete; + +import java.util.List; + +import org.hibernate.Transaction; +import org.hibernate.stat.spi.StatisticsImplementor; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * @author Gavin King + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ondelete/Person.hbm.xml" +) +@SessionFactory( + generateStatistics = true +) +public class OnDeleteTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> { + session.createQuery( "delete from Salesperson" ).executeUpdate(); + session.createQuery( "delete from Employee" ).executeUpdate(); + session.createQuery( "delete from Person" ).executeUpdate(); + } + ); + } + + @Test + @RequiresDialectFeature( + feature = DialectFeatureChecks.SupportsCircularCascadeDeleteCheck.class, + comment = "db/dialect does not support circular cascade delete constraints" + ) + public void testJoinedSubclass(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Salesperson mark = new Salesperson(); + mark.setName( "Mark" ); + mark.setTitle( "internal sales" ); + mark.setSex( 'M' ); + mark.setAddress( "buckhead" ); + mark.setZip( "30305" ); + mark.setCountry( "USA" ); + + Person joe = new Person(); + joe.setName( "Joe" ); + joe.setAddress( "San Francisco" ); + joe.setZip( "XXXXX" ); + joe.setCountry( "USA" ); + joe.setSex( 'M' ); + joe.setSalesperson( mark ); + mark.getCustomers().add( joe ); + + session.save( mark ); + + session.getTransaction().commit(); + + final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + + assertThat( statistics.getEntityInsertCount(), is( 2L ) ); + assertThat( statistics.getPrepareStatementCount(), is( 5L ) ); + + statistics.clear(); + + Transaction t = session.beginTransaction(); + session.delete( mark ); + t.commit(); + + assertThat( statistics.getEntityDeleteCount(), is( 2L ) ); + if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsCascadeDelete() ) { + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); + } + + session.beginTransaction(); + List names = session.createQuery( "select name from Person" ).list(); + assertTrue( names.isEmpty() ); + } + ); + + } + +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.hbm.xml similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.hbm.xml index 6e127dfcb7..e7a65147b3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.hbm.xml @@ -17,7 +17,7 @@ --> diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.java index 4463bfb81c..bdd493a1c2 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Person.java @@ -6,7 +6,7 @@ */ //$Id: Person.java 7119 2005-06-12 22:03:30Z oneovthafew $ -package org.hibernate.test.ondelete; +package org.hibernate.orm.test.ondelete; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Salesperson.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Salesperson.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/Salesperson.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Salesperson.java index 13e828ecc8..d287e7580b 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/Salesperson.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/Salesperson.java @@ -6,7 +6,7 @@ */ //$Id: Salesperson.java 7119 2005-06-12 22:03:30Z oneovthafew $ -package org.hibernate.test.ondelete; +package org.hibernate.orm.test.ondelete; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/ToOneOnDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/ToOneOnDeleteTest.java new file mode 100644 index 0000000000..8b208335b5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/ToOneOnDeleteTest.java @@ -0,0 +1,127 @@ +package org.hibernate.orm.test.ondelete.toone; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; + +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.dialect.SybaseDialect; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + + +/** + * @author Vlad Mihalcea + */ +@DomainModel( + annotatedClasses = { + ToOneOnDeleteTest.Parent.class, + ToOneOnDeleteTest.Child.class, + ToOneOnDeleteTest.GrandChild.class + } +) +@SessionFactory +public class ToOneOnDeleteTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> { + session.createQuery( "delete from Parent" ).executeUpdate(); + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from GrandChild" ).executeUpdate(); + } + ); + } + + @Test + @SkipForDialect( + dialectClass = SybaseDialect.class, + matchSubTypes = true, + reason = "HHH-13559 on-delete=\"cascade\" is not supported for unidirectional to-one associations using Sybase" + ) + public void testManyToOne(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent parent = new Parent(); + parent.id = 1L; + session.persist( parent ); + + Child child1 = new Child(); + child1.id = 1L; + child1.parent = parent; + session.persist( child1 ); + + GrandChild grandChild11 = new GrandChild(); + grandChild11.id = 1L; + grandChild11.parent = child1; + session.persist( grandChild11 ); + + Child child2 = new Child(); + child2.id = 2L; + child2.parent = parent; + session.persist( child2 ); + + GrandChild grandChild21 = new GrandChild(); + grandChild21.id = 2L; + grandChild21.parent = child2; + session.persist( grandChild21 ); + + GrandChild grandChild22 = new GrandChild(); + grandChild22.id = 3L; + grandChild22.parent = child2; + session.persist( grandChild22 ); + } + ); + + scope.inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1L ); + session.delete( parent ); + } + ); + } + + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + } + + @Entity(name = "Child") + public static class Child { + + @Id + private Long id; + + private String name; + + @ManyToOne + @OnDelete(action = OnDeleteAction.CASCADE) + private Parent parent; + } + + @Entity(name = "GrandChild") + public static class GrandChild { + + @Id + private Long id; + + private String name; + + @OneToOne + @OnDelete(action = OnDeleteAction.CASCADE) + private Child parent; + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Child.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Child.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Child.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Child.java index 320a0cb391..4c45879048 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Child.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Child.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondelete.toone.hbm; +package org.hibernate.orm.test.ondelete.toone.hbm; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/GrandChild.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/GrandChild.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/GrandChild.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/GrandChild.java index 2bfab9373d..32555f4674 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/GrandChild.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/GrandChild.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondelete.toone.hbm; +package org.hibernate.orm.test.ondelete.toone.hbm; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Parent.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Parent.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Parent.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Parent.java index ada976a039..4f722f069a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/Parent.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/Parent.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondelete.toone.hbm; +package org.hibernate.orm.test.ondelete.toone.hbm; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml index c15feb22ca..a6a4a3f7bb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml @@ -5,7 +5,7 @@ ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later. ~ See the lgpl.txt file in the root directory or . --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java new file mode 100644 index 0000000000..e9d34fb905 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java @@ -0,0 +1,84 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ondelete.toone.hbm; + +import org.hibernate.dialect.SybaseDialect; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + + +/** + * @author Vlad Mihalcea + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ondelete/toone/hbm/ToOneOnDelete.hbm.xml" +) +@SessionFactory +public class ToOneOnDeleteHbmTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> { + session.createQuery( "delete from Parent" ).executeUpdate(); + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from GrandChild" ).executeUpdate(); + } + ); + } + + @Test + @SkipForDialect( + dialectClass = SybaseDialect.class, + matchSubTypes = true, + reason = "HHH-13559 on-delete=\"cascade\" is not supported for unidirectional to-one associations using Sybase" + ) + public void testManyToOne(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent parent = new Parent(); + parent.setId( 1L ); + session.persist( parent ); + + Child child1 = new Child(); + child1.setId( 1L ); + child1.setParent( parent ); + session.persist( child1 ); + + GrandChild grandChild11 = new GrandChild(); + grandChild11.setId( 1L ); + grandChild11.setParent( child1 ); + session.persist( grandChild11 ); + + Child child2 = new Child(); + child2.setId( 2L ); + child2.setParent( parent ); + session.persist( child2 ); + + GrandChild grandChild21 = new GrandChild(); + grandChild21.setId( 2L ); + grandChild21.setParent( child2 ); + session.persist( grandChild21 ); + + } + ); + + + scope.inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1L ); + session.delete( parent ); + } + ); + } + +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Inventory.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Inventory.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ondemandload/Inventory.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Inventory.java index caeeaa654d..7487e8ce39 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Inventory.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Inventory.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondemandload; +package org.hibernate.orm.test.ondemandload; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/LazyLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/LazyLoadingTest.java new file mode 100644 index 0000000000..36ded46a22 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/LazyLoadingTest.java @@ -0,0 +1,182 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +package org.hibernate.orm.test.ondemandload; + +import java.math.BigDecimal; + +import org.hibernate.Hibernate; +import org.hibernate.cfg.Environment; +import org.hibernate.stat.spi.StatisticsImplementor; + +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; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +@DomainModel( + annotatedClasses = { + Store.class, + Inventory.class, + Product.class + } +) +@SessionFactory( + generateStatistics = true +) +@ServiceRegistry( + settings = { + @Setting(name = Environment.ENABLE_LAZY_LOAD_NO_TRANS, value = "true") + } +) +public class LazyLoadingTest { + + @BeforeEach + public void setUpData(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Store store = new Store( 1 ) + .setName( "Acme Super Outlet" ); + session.persist( store ); + + Product product = new Product( "007" ) + .setName( "widget" ) + .setDescription( "FooBar" ); + session.persist( product ); + + store.addInventoryProduct( product ) + .setQuantity( 10L ) + .setStorePrice( new BigDecimal( 500 ) ); + } + ); + } + + @AfterEach + public void cleanUpData(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.delete( session.get( Store.class, 1 ) ); + session.delete( session.get( Product.class, "007" ) ); + } + ); + } + + @Test + public void testLazyCollectionLoadingWithClearedSession(SessionFactoryScope scope) { + final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + + scope.inTransaction( + session -> { + // first load the store, making sure collection is not initialized + Store store = (Store) session.get( Store.class, 1 ); + assertNotNull( store ); + assertFalse( Hibernate.isInitialized( store.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 1l ) ); + assertThat( statistics.getSessionCloseCount(), is( 0l ) ); + + // then clear session and try to initialize collection + session.clear(); + store.getInventories().size(); + assertTrue( Hibernate.isInitialized( store.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 2l ) ); + assertThat( statistics.getSessionCloseCount(), is( 1l ) ); + + session.clear(); + store = (Store) session.get( Store.class, 1 ); + assertNotNull( store ); + assertFalse( Hibernate.isInitialized( store.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 2l ) ); + assertThat( statistics.getSessionCloseCount(), is( 1l ) ); + + session.clear(); + store.getInventories().iterator(); + assertTrue( Hibernate.isInitialized( store.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 3l ) ); + assertThat( statistics.getSessionCloseCount(), is( 2l ) ); + } + ); + } + + @Test + public void testLazyCollectionLoadingWithClosedSession(SessionFactoryScope scope) { + final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + + Store s = scope.fromTransaction( + session -> { + // first load the store, making sure collection is not initialized + Store store = session.get( Store.class, 1 ); + assertNotNull( store ); + assertFalse( Hibernate.isInitialized( store.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 1l ) ); + assertThat( statistics.getSessionCloseCount(), is( 0l ) ); + return store; + } + ); + + + // close the session and try to initialize collection + + assertThat( statistics.getSessionOpenCount(), is( 1l ) ); + assertThat( statistics.getSessionCloseCount(), is( 1l ) ); + + s.getInventories().size(); + assertTrue( Hibernate.isInitialized( s.getInventories() ) ); + + assertThat( statistics.getSessionOpenCount(), is( 2l ) ); + assertThat( statistics.getSessionCloseCount(), is( 2l ) ); + } + + @Test + public void testLazyEntityLoadingWithClosedSession(SessionFactoryScope scope) { + final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + + Store s = scope.fromTransaction( + session -> { + // first load the store, making sure it is not initialized + Store store = session.load( Store.class, 1 ); + assertNotNull( store ); + assertFalse( Hibernate.isInitialized( store ) ); + + assertThat( statistics.getSessionOpenCount(), is( 1l ) ); + assertThat( statistics.getSessionCloseCount(), is( 0l ) ); + return store; + } + ); + + + // close the session and try to initialize store + + assertThat( statistics.getSessionOpenCount(), is( 1l ) ); + assertThat( statistics.getSessionCloseCount(), is( 1l ) ); + + s.getName(); + assertTrue( Hibernate.isInitialized( s ) ); + + assertThat( statistics.getSessionOpenCount(), is( 2l ) ); + assertThat( statistics.getSessionCloseCount(), is( 2l ) ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Product.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Product.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ondemandload/Product.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Product.java index c31b665106..46cabbd064 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Product.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Product.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondemandload; +package org.hibernate.orm.test.ondemandload; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Store.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Store.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ondemandload/Store.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Store.java index 95df78e6ea..22148101dc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/Store.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/Store.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ondemandload; +package org.hibernate.orm.test.ondemandload; import javax.persistence.CascadeType; import javax.persistence.Column; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/cache/CacheLazyLoadNoTransTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/cache/CacheLazyLoadNoTransTest.java new file mode 100644 index 0000000000..8466b0d9d5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ondemandload/cache/CacheLazyLoadNoTransTest.java @@ -0,0 +1,227 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ondemandload.cache; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Cacheable; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import org.hibernate.Hibernate; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.cache.spi.access.CollectionDataAccess; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Environment; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.persister.collection.CollectionPersister; + +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.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * @author Janario Oliveira + */ +@DomainModel( + annotatedClasses = { + CacheLazyLoadNoTransTest.Application.class, + CacheLazyLoadNoTransTest.Customer.class, + CacheLazyLoadNoTransTest.Item.class + } +) +@SessionFactory +@ServiceRegistry( + settings = { + @Setting(name = AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, value = "true"), + @Setting(name = Environment.USE_SECOND_LEVEL_CACHE, value = "true"), + @Setting(name = Environment.USE_QUERY_CACHE, value = "true"), + @Setting(name = Environment.CACHE_PROVIDER_CONFIG, value = "true"), + } +) +public class CacheLazyLoadNoTransTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> { + session.createQuery( "delete from Application" ).executeUpdate(); + session.createQuery( "delete from Item" ).executeUpdate(); + session.createQuery( "delete from Customer" ).executeUpdate(); + } + ); + } + + @Test + public void hibernateInitialize(SessionFactoryScope scope) { + Customer customer = new Customer(); + Item item1 = new Item( customer ); + Item item2 = new Item( customer ); + customer.boughtItems.add( item1 ); + customer.boughtItems.add( item2 ); + persist( customer, scope ); + + customer = find( Customer.class, customer.id, scope ); + assertFalse( Hibernate.isInitialized( customer.boughtItems ) ); + Hibernate.initialize( customer.boughtItems ); + assertTrue( Hibernate.isInitialized( customer.boughtItems ) ); + } + + @Test + public void testOneToMany(SessionFactoryScope scope) { + Customer customer = new Customer(); + Item item1 = new Item( customer ); + Item item2 = new Item( customer ); + customer.boughtItems.add( item1 ); + customer.boughtItems.add( item2 ); + persist( customer, scope ); + + //init cache + assertFalse( isCached( customer.id, Customer.class, "boughtItems", scope ) ); + customer = find( Customer.class, customer.id, scope ); + assertThat( customer.boughtItems.size(), is( 2 ) ); + + //read from cache + assertTrue( isCached( customer.id, Customer.class, "boughtItems", scope ) ); + customer = find( Customer.class, customer.id, scope ); + assertThat( customer.boughtItems.size(), is( 2 ) ); + } + + @Test + public void testManyToMany(SessionFactoryScope scope) { + Application application = new Application(); + persist( application, scope ); + Customer customer = new Customer(); + customer.applications.add( application ); + application.customers.add( customer ); + persist( customer, scope ); + + //init cache + assertFalse( isCached( customer.id, Customer.class, "applications", scope ) ); + assertFalse( isCached( application.id, Application.class, "customers", scope ) ); + + customer = find( Customer.class, customer.id, scope ); + assertThat( customer.applications.size(), is( 1 ) ); + application = find( Application.class, application.id, scope ); + assertThat( application.customers.size(), is( 1 ) ); + + assertTrue( isCached( customer.id, Customer.class, "applications", scope ) ); + assertTrue( isCached( application.id, Application.class, "customers", scope ) ); + + //read from cache + customer = find( Customer.class, customer.id, scope ); + assertThat( customer.applications.size(), is( 1 ) ); + application = find( Application.class, application.id, scope ); + assertThat( application.customers.size(), is( 1 ) ); + } + + private void persist(Object entity, SessionFactoryScope scope) { + scope.inTransaction( + session -> + session.persist( entity ) + ); + } + + private E find(Class entityClass, int id, SessionFactoryScope scope) { + return scope.fromSession( + session -> + session.get( entityClass, id ) + ); + } + + private boolean isCached(Serializable id, Class entityClass, String attr, SessionFactoryScope scope) { + Object value = scope.fromSession( + session -> { + final SessionFactoryImplementor sessionFactory = scope.getSessionFactory(); + CollectionPersister persister = sessionFactory.getCollectionPersister( entityClass.getName() + "." + attr ); + CollectionDataAccess cache = persister.getCacheAccessStrategy(); + Object key = cache.generateCacheKey( id, persister, sessionFactory, session.getTenantIdentifier() ); + Object cachedValue = cache.get( session, key ); + return cachedValue; + } + ); + + return value != null; + } + + + @Entity(name = "Application") + @Table(name = "application") + @Cacheable + public static class Application { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @ManyToMany(mappedBy = "applications") + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + private List customers = new ArrayList<>(); + } + + @Entity(name = "Customer") + @Table(name = "customer") + @Cacheable + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + public static class Customer { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @ManyToMany + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + private List applications = new ArrayList<>(); + + @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + private List boughtItems = new ArrayList<>(); + } + + @Entity(name = "Item") + @Table(name = "item") + @Cacheable + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + public static class Item { + @Id + @GeneratedValue + private Integer id; + @ManyToOne + @JoinColumn(name = "customer_id") + private Customer customer; + + private String name; + + protected Item() { + } + + public Item(Customer customer) { + this.customer = customer; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/AbstractOperationTestCase.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/AbstractOperationTestCase.java new file mode 100644 index 0000000000..b287460546 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/AbstractOperationTestCase.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import org.hibernate.cfg.Environment; +import org.hibernate.stat.spi.StatisticsImplementor; + +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 static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Steve Ebersole + */ +@SessionFactory(generateStatistics = true) +@DomainModel( + xmlMappings = { + "org/hibernate/orm/test/ops/Node.hbm.xml", + "org/hibernate/orm/test/ops/Employer.hbm.xml", + "org/hibernate/orm/test/ops/OptLockEntity.hbm.xml", + "org/hibernate/orm/test/ops/OneToOne.hbm.xml", + "org/hibernate/orm/test/ops/Competition.hbm.xml" + } +) +@ServiceRegistry( + settings = @Setting(name = Environment.STATEMENT_BATCH_SIZE, value = "0") +) +public abstract class AbstractOperationTestCase { + + public String getCacheConcurrencyStrategy() { + return null; + } + + protected void clearCounts(SessionFactoryScope scope) { + getStatistics( scope ).clear(); + } + + protected void assertInsertCount(int expected, SessionFactoryScope scope) { + int inserts = (int) getStatistics( scope ).getEntityInsertCount(); + assertThat( "unexpected insert count", inserts, is( expected ) ); + } + + protected void assertUpdateCount(int expected, SessionFactoryScope scope) { + int updates = (int) getStatistics( scope ).getEntityUpdateCount(); + assertThat( "unexpected update counts", updates, is( expected ) ); + } + + protected void assertDeleteCount(int expected, SessionFactoryScope scope) { + int deletes = (int) getStatistics( scope ).getEntityDeleteCount(); + assertThat( "unexpected delete counts", deletes, is( expected ) ); + } + + private StatisticsImplementor getStatistics(SessionFactoryScope scope) { + return scope.getSessionFactory().getStatistics(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Address.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Address.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Address.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Address.java index f25da937ac..24827c15e8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Address.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Address.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Category.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Category.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Category.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Category.java index 765ca24c32..b814474d0c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Category.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Category.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Competition.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.hbm.xml similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Competition.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.hbm.xml index b8dff6914e..971e8623bc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Competition.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Competition.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Competition.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.java index e3a138cd7b..67337ba51b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Competition.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competition.java @@ -6,7 +6,7 @@ */ //$Id: $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.ArrayList; import java.util.List; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Competitor.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competitor.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Competitor.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competitor.java index 3d44e6290b..343ff08173 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Competitor.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Competitor.java @@ -6,7 +6,7 @@ */ //$Id: $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CreateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CreateTest.java new file mode 100755 index 0000000000..13aa71af62 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CreateTest.java @@ -0,0 +1,244 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.ArrayList; +import java.util.Collection; +import javax.persistence.PersistenceException; + +import org.hibernate.PersistentObjectException; +import org.hibernate.dialect.AbstractHANADialect; +import org.hibernate.exception.ConstraintViolationException; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Gavin King + */ +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsNoColumnInsert.class) +public class CreateTest extends AbstractOperationTestCase { + + @Test + @SuppressWarnings({ "unchecked" }) + public void testNoUpdatesOnCreateVersionedWithCollection(SessionFactoryScope scope) { + clearCounts( scope ); + + VersionedEntity root = new VersionedEntity( "root", "root" ); + scope.inTransaction( + session -> { + VersionedEntity child = new VersionedEntity( "c1", "child-1" ); + root.getChildren().add( child ); + child.setParent( root ); + session.save( root ); + } + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 0, scope ); + + scope.inTransaction( + session -> + session.delete( root ) + ); + + assertUpdateCount( 0, scope ); + assertDeleteCount( 2, scope ); + } + + @Test + public void testCreateTree(SessionFactoryScope scope) { + clearCounts( scope ); + + scope.inTransaction( + session -> { + Node root = new Node( "root" ); + Node child = new Node( "child" ); + root.addChild( child ); + session.persist( root ); + } + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + + scope.inTransaction( + session -> { + Node root = session.get( Node.class, "root" ); + Node child2 = new Node( "child2" ); + root.addChild( child2 ); + } + ); + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + } + + @Test + public void testCreateTreeWithGeneratedId(SessionFactoryScope scope) { + clearCounts( scope ); + + NumberedNode root = new NumberedNode( "root" ); + scope.inTransaction( + session -> { + NumberedNode child = new NumberedNode( "child" ); + root.addChild( child ); + session.persist( root ); + } + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + + scope.inTransaction( + session -> { + NumberedNode r = session.get( NumberedNode.class, root.getId() ); + NumberedNode child2 = new NumberedNode( "child2" ); + r.addChild( child2 ); + } + ); + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + } + + @Test + public void testCreateException(SessionFactoryScope scope) { + Node dupe = new Node( "dupe" ); + scope.inTransaction( + session -> { + session.persist( dupe ); + session.persist( dupe ); + } + ); + + scope.inSession( + session -> { + try { + session.beginTransaction(); + session.persist( dupe ); + session.getTransaction().commit(); + fail( "Expecting constraint failure" ); + } + catch (PersistenceException e) { + + //verify that an exception is thrown! + assertTyping( ConstraintViolationException.class, e.getCause() ); + } + finally { + if(session.getTransaction().isActive()){ + session.getTransaction().rollback(); + } + } + } + ); + + Node nondupe = new Node( "nondupe" ); + nondupe.addChild( dupe ); + + scope.inSession( + session -> { + try { + session.beginTransaction(); + session.persist( nondupe ); + session.getTransaction().commit(); + fail( "Expecting constraint failure" ); + } + catch (PersistenceException e) { + //verify that an exception is thrown! + assertTyping( ConstraintViolationException.class, e.getCause() ); + } + finally { + if(session.getTransaction().isActive()){ + session.getTransaction().rollback(); + } + } + } + ); + } + + @Test + public void testCreateExceptionWithGeneratedId(SessionFactoryScope scope) { + NumberedNode dupe = new NumberedNode( "dupe" ); + scope.inTransaction( + session -> { + session.persist( dupe ); + session.persist( dupe ); + } + ); + + scope.inTransaction( + session -> { + try { + session.persist( dupe ); + fail( "Expecting failure" ); + } + catch (PersistenceException e) { + //verify that an exception is thrown! + assertTyping( PersistentObjectException.class, e.getCause() ); + } + } + ); + + NumberedNode nondupe = new NumberedNode( "nondupe" ); + nondupe.addChild( dupe ); + + scope.inTransaction( + session -> { + try { + session.persist( nondupe ); + fail( "Expecting failure" ); + } + catch (PersistenceException e) { + //verify that an exception is thrown! + assertTyping( PersistentObjectException.class, e.getCause() ); + } + } + ); + } + + @Test + @SuppressWarnings({ "unchecked" }) + @SkipForDialect(dialectClass = AbstractHANADialect.class, reason = " HANA doesn't support tables consisting of only a single auto-generated column") + public void testBasic(SessionFactoryScope scope) throws Exception { + Employer er = new Employer(); + Employee ee = new Employee(); + scope.inTransaction( + session -> { + session.persist( ee ); + Collection erColl = new ArrayList(); + Collection eeColl = new ArrayList(); + erColl.add( ee ); + eeColl.add( er ); + er.setEmployees( erColl ); + ee.setEmployers( eeColl ); + } + ); + + scope.inTransaction( + session -> { + Employer er1 = session.load( Employer.class, er.getId() ); + assertNotNull( er1 ); + assertNotNull( er1.getEmployees() ); + assertThat( er1.getEmployees().size(), is( 1 ) ); + Employee eeFromDb = (Employee) er1.getEmployees().iterator().next(); + assertThat( eeFromDb.getId(), is( ee.getId() ) ); + } + ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CustomEntityCopyObserver.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CustomEntityCopyObserver.java new file mode 100644 index 0000000000..823378d445 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/CustomEntityCopyObserver.java @@ -0,0 +1,28 @@ +package org.hibernate.orm.test.ops; + +import org.hibernate.event.spi.EntityCopyObserver; +import org.hibernate.event.spi.EventSource; + +public class CustomEntityCopyObserver implements EntityCopyObserver { + + @Override + public void entityCopyDetected( + Object managedEntity, + Object mergeEntity1, + Object mergeEntity2, + EventSource session) { + if ( Category.class.isInstance( managedEntity ) ) { + throw new IllegalStateException( + String.format( "Entity copies of type [%s] not allowed", Category.class.getName() ) + ); + } + } + + @Override + public void topLevelMergeComplete(EventSource session) { + } + + @Override + public void clear() { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/DeleteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/DeleteTest.java new file mode 100644 index 0000000000..29d55097f4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/DeleteTest.java @@ -0,0 +1,94 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +/** + * @author Steve Ebersole + */ +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsNoColumnInsert.class) +public class DeleteTest extends AbstractOperationTestCase { + + @Test + @SuppressWarnings({ "unchecked" }) + public void testDeleteVersionedWithCollectionNoUpdate(SessionFactoryScope scope) { + // test adapted from HHH-1564... + scope.inTransaction( + session -> { + VersionedEntity c = new VersionedEntity( "c1", "child-1" ); + VersionedEntity p = new VersionedEntity( "root", "root" ); + p.getChildren().add( c ); + c.setParent( p ); + session.save( p ); + } + ); + + clearCounts( scope ); + + scope.inTransaction( + session -> { + VersionedEntity loadedParent = session.get( VersionedEntity.class, "root" ); + session.delete( loadedParent ); + } + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 2, scope ); + } + + @Test + public void testNoUpdateOnDelete(SessionFactoryScope scope) { + Node node = new Node( "test" ); + scope.inTransaction( + session -> + session.persist( node ) + ); + + clearCounts( scope ); + + scope.inTransaction( + session -> + session.delete( node ) + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + } + + @Test + @SuppressWarnings({ "unchecked" }) + public void testNoUpdateOnDeleteWithCollection(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Node parent = new Node( "parent" ); + Node child = new Node( "child" ); + parent.getCascadingChildren().add( child ); + session.persist( parent ); + } + ); + + + clearCounts( scope ); + + scope.inTransaction( + session -> { + Node parent = session.get( Node.class, "parent" ); + session.delete( parent ); + } + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + assertDeleteCount( 2, scope ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Employee.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employee.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Employee.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employee.java index 6d020672d9..b2d53982bf 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Employee.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employee.java @@ -6,7 +6,7 @@ */ //$Id: Employee.java 5686 2005-02-12 07:27:32Z steveebersole $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.io.Serializable; import java.util.Collection; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Employer.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.hbm.xml similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Employer.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.hbm.xml index 64d600065b..3e196ef16a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Employer.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Employer.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Employer.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.java index d7226ab56b..b21cc73b8c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Employer.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Employer.java @@ -6,7 +6,7 @@ */ //$Id: Employer.java 8670 2005-11-25 17:36:29Z epbernard $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.io.Serializable; import java.util.Collection; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/GetLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/GetLoadTest.java new file mode 100644 index 0000000000..e1b9a19542 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/GetLoadTest.java @@ -0,0 +1,141 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import org.hibernate.Hibernate; +import org.hibernate.cfg.Environment; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * @author Gavin King + */ +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsNoColumnInsert.class) +@DomainModel( + xmlMappings = { + "org/hibernate/orm/test/ops/Node.hbm.xml", + "org/hibernate/orm/test/ops/Employer.hbm.xml" + } +) +@SessionFactory( + generateStatistics = true +) +@ServiceRegistry( + settings = { + @Setting(name = Environment.STATEMENT_BATCH_SIZE, value = "0") + } +) +public class GetLoadTest { + + @Test + public void testGetLoad(SessionFactoryScope scope) { + clearCounts( scope ); + + Employer emp = new Employer(); + Node node = new Node( "foo" ); + Node parent = new Node( "bar" ); + scope.inTransaction( + session -> { + session.persist( emp ); + parent.addChild( node ); + session.persist( parent ); + } + ); + + scope.inTransaction( + session -> { + Employer e = session.get( Employer.class, emp.getId() ); + assertTrue( Hibernate.isInitialized( e ) ); + assertFalse( Hibernate.isInitialized( e.getEmployees() ) ); + Node n = session.get( Node.class, node.getName() ); + assertTrue( Hibernate.isInitialized( n ) ); + assertFalse( Hibernate.isInitialized( n.getChildren() ) ); + assertFalse( Hibernate.isInitialized( n.getParent() ) ); + assertNull( session.get( Node.class, "xyz" ) ); + } + ); + + scope.inTransaction( + session -> { + Employer e = session.load( Employer.class, emp.getId() ); + e.getId(); + assertFalse( Hibernate.isInitialized( e ) ); + Node n = session.load( Node.class, node.getName() ); + assertThat( n.getName(), is( "foo" ) ); + assertFalse( Hibernate.isInitialized( n ) ); + } + ); + + scope.inTransaction( + session -> { + Employer e = (Employer) session.get( "org.hibernate.orm.test.ops.Employer", emp.getId() ); + assertTrue( Hibernate.isInitialized( e ) ); + Node n = (Node) session.get( "org.hibernate.orm.test.ops.Node", node.getName() ); + assertTrue( Hibernate.isInitialized( n ) ); + } + ); + + scope.inTransaction( + session -> { + Employer e = (Employer) session.load( "org.hibernate.orm.test.ops.Employer", emp.getId() ); + e.getId(); + assertFalse( Hibernate.isInitialized( e ) ); + Node n = (Node) session.load( "org.hibernate.orm.test.ops.Node", node.getName() ); + assertThat( n.getName(), is( "foo" ) ); + assertFalse( Hibernate.isInitialized( n ) ); + } + ); + + assertFetchCount( 0, scope ); + } + + @Test + public void testGetAfterDelete(SessionFactoryScope scope) { + clearCounts( scope ); + + Employer emp = new Employer(); + + scope.inTransaction( + session -> + session.persist( emp ) + ); + + Employer e = scope.fromTransaction( + session -> { + session.delete( emp ); + return session.get( Employer.class, emp.getId() ); + } + ); + + assertNull( e, "get did not return null after delete" ); + } + + private void clearCounts(SessionFactoryScope scope) { + scope.getSessionFactory().getStatistics().clear(); + } + + private void assertFetchCount(int count, SessionFactoryScope scope) { + int fetches = (int) scope.getSessionFactory().getStatistics().getEntityFetchCount(); + assertThat( fetches, is( count ) ); + } + +} + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/HANANoColumnInsertTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/HANANoColumnInsertTest.java new file mode 100644 index 0000000000..43835026ed --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/HANANoColumnInsertTest.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.dialect.AbstractHANADialect; +import org.hibernate.engine.spi.SessionFactoryImplementor; + +import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; +import org.hibernate.testing.orm.junit.RequiresDialect; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.fail; + + +/** + * @author Vlad Mihalcea + */ +@RequiresDialect(value = AbstractHANADialect.class) +public class HANANoColumnInsertTest extends BaseSessionFactoryFunctionalTest { + + @Override + protected String[] getOrmXmlFiles() { + return new String[] { + "org/hibernate/orm/test/ops/Competition.hbm.xml" + }; + } + + @Override + public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) { + SessionFactoryImplementor sessionFactoryImplementor = null; + try { + sessionFactoryImplementor = produceSessionFactory( model ); + + fail( "Should have thrown MappingException!" ); + return sessionFactoryImplementor; + } + catch (MappingException e) { + assertThat( + + e.getMessage(), + is( "The INSERT statement for table [Competition] contains no column, and this is not supported by [" + getDialect() + .getClass() + .getName() + "]" ) + ); + } + return sessionFactoryImplementor; + } + + @Test + public void test() { + inTransaction( + session -> { + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.hbm.xml similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.hbm.xml index d18693998d..82ecb830b8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.java index ae01aa7a7e..182ce97b77 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Hoarder.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Hoarder.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/HoarderOrphanDelete.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/HoarderOrphanDelete.hbm.xml similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/HoarderOrphanDelete.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/HoarderOrphanDelete.hbm.xml index f490251bbb..3f92bce677 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/HoarderOrphanDelete.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/HoarderOrphanDelete.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Item.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Item.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Item.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Item.java index 37c44a1820..632d4e18b2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Item.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Item.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.ArrayList; import java.util.HashSet; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeManagedAndCopiesAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeManagedAndCopiesAllowedTest.java similarity index 56% rename from hibernate-core/src/test/java/org/hibernate/test/ops/MergeManagedAndCopiesAllowedTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeManagedAndCopiesAllowedTest.java index 1f6ceb5926..ecb5bd2bb5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeManagedAndCopiesAllowedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeManagedAndCopiesAllowedTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.HashSet; import java.util.Set; @@ -17,76 +17,74 @@ import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OneToOne; -import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.AvailableSettings; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +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.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; +import static junit.framework.TestCase.assertSame; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; /** * A 1 ------------> 1 B 1 ----------> 1 C - * 1 1 - * | | - * | | - * V V - * 1 N - * D 1------------>N E - * + * 1 1 + * | | + * | | + * V V + * 1 N + * D 1------------>N E * * @author Gail Badner */ -public class MergeManagedAndCopiesAllowedTest extends BaseCoreFunctionalTestCase { - - protected Class[] getAnnotatedClasses() { - return new Class[]{ - A.class, - B.class, - C.class, - D.class, - E.class - }; - } - - protected void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( "hibernate.event.merge.entity_copy_observer", "allow" ); - } +@DomainModel( + annotatedClasses = { + MergeManagedAndCopiesAllowedTest.A.class, + MergeManagedAndCopiesAllowedTest.B.class, + MergeManagedAndCopiesAllowedTest.C.class, + MergeManagedAndCopiesAllowedTest.D.class, + MergeManagedAndCopiesAllowedTest.E.class + } +) +@SessionFactory +@ServiceRegistry(settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "allow")) +public class MergeManagedAndCopiesAllowedTest { @Test - public void testIt() { + public void testIt(SessionFactoryScope scope) { A a = new A(); a.b = new B(); a.b.d = new D(); a.b.d.dEs.add( new E() ); - doInHibernate( - this::sessionFactory, session -> { - session.persist( a ); - } + scope.inTransaction( + session -> + session.persist( a ) ); - doInHibernate( - this::sessionFactory, session -> { - A aGet= session.get( A.class, a.id ); + scope.inTransaction( + session -> { + A aGet = session.get( A.class, a.id ); aGet.b.c = new C(); Set copies = new HashSet<>(); for ( E e : aGet.b.d.dEs ) { - copies.add ( new E( e.id, "description" ) ); + copies.add( new E( e.id, "description" ) ); } aGet.b.c.cEs.addAll( copies ); session.merge( aGet ); } ); - doInHibernate( - this::sessionFactory, session -> { - A aGet= session.get( A.class, a.id ); + scope.inTransaction( + session -> { + A aGet = session.get( A.class, a.id ); E e = aGet.b.c.cEs.iterator().next(); assertSame( e, aGet.b.d.dEs.iterator().next() ); - assertEquals( "description", e.description ); + assertThat( e.description, is( "description" ) ); } ); } @@ -97,7 +95,7 @@ public class MergeManagedAndCopiesAllowedTest extends BaseCoreFunctionalTestCase @GeneratedValue private int id; - @OneToOne(fetch=FetchType.EAGER, cascade = CascadeType.ALL) + @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) private B b; } @@ -145,7 +143,8 @@ public class MergeManagedAndCopiesAllowedTest extends BaseCoreFunctionalTestCase private String description; - E() {} + E() { + } E(int id, String description) { this.id = id; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java similarity index 62% rename from hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java index e9fe60434b..59ea76b215 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedLoggedTest.java @@ -4,21 +4,20 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; -import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.AvailableSettings; + +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.Setting; /** * Tests merging multiple detached representations of the same entity when explicitly allowed and logged. * * @author Gail Badner */ +@ServiceRegistry( + settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "log") +) public class MergeMultipleEntityCopiesAllowedLoggedTest extends MergeMultipleEntityCopiesAllowedTest { - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( - "hibernate.event.merge.entity_copy_observer", - "log" - ); - } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java new file mode 100644 index 0000000000..26df800164 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java @@ -0,0 +1,495 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.cfg.AvailableSettings; + +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.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests merging multiple detached representations of the same entity (allowed) + * where some associations include cascade="delete-orphan" + * + * @author Gail Badner + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/HoarderOrphanDelete.hbm.xml" +) +@SessionFactory +@ServiceRegistry( + settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "allow") +) +public class MergeMultipleEntityCopiesAllowedOrphanDeleteTest { + + @Test + @FailureExpected(jiraKey = "HHH-9240") + public void testTopLevelUnidirOneToManyBackrefWithNewElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + + ); + + assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); + + Category category = new Category(); + category.setName( "category" ); + + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + // The following will fail due to PropertyValueException because item1 will + // be removed from the inverted merge map when the operation cascades to item1_1. + Item item1Merged = (Item) session.merge( item1 ); + // top-level collection should win + assertThat( item1Merged.getSubItemsBackref().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyBackrefWithNewElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getSubItemsBackref() ); + return item; + } + ); + + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + + // Add a new SubItem to the Item representation that will be in a nested association. + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1_1.getSubItemsBackref().add( subItem2 ); + + category.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // The resulting collection should contain the added element + assertThat( item1Merged.getSubItemsBackref().size(), is( 2 ) ); + assertThat( item1Merged.getSubItemsBackref().get( 0 ).getName(), is( "subItem1 name" ) ); + assertThat( item1Merged.getSubItemsBackref().get( 1 ).getName(), is( "subItem2 name" ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 2 ) ); + assertThat( item.getSubItemsBackref().get( 0 ).getName(), is( "subItem1 name" ) ); + assertThat( item.getSubItemsBackref().get( 1 ).getName(), is( "subItem2 name" ) ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyBackrefWithRemovedElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); + + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + // remove subItem1 from top-level Item + item1.getSubItemsBackref().remove( subItem1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // element should be removed + assertThat( item1Merged.getSubItemsBackref().size(), is( 1 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 1 ) ); + // because cascade includes "delete-orphan" the removed SubItem should have been deleted. + SubItem subItem = session.get( SubItem.class, subItem1.getId() ); + assertNull( subItem ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyBackrefWithRemovedElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getSubItemsBackref() ); + return item; + } + ); + + // remove subItem1 from the nested Item + item1_1.getSubItemsBackref().remove( subItem1 ); + + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the element should have been removed + assertThat( item1Merged.getSubItemsBackref().size(), is( 1 ) ); + assertTrue( item1Merged.getSubItemsBackref().contains( subItem2 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 1 ) ); + assertTrue( item.getSubItemsBackref().contains( subItem2 ) ); + // because cascade includes "delete-orphan" the removed SubItem should have been deleted. + SubItem subItem = session.get( SubItem.class, subItem1.getId() ); + assertNull( subItem ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyNoBackrefWithNewElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> + session.get( Category.class, category1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); + + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyNoBackrefWithNewElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + Hibernate.initialize( category.getSubCategories() ); + return category; + } + ); + + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1_1.getSubCategories().add( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + // new element should be there + assertThat( category1Merged.getSubCategories().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyNoBackrefWithRemovedElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> + session.get( Category.class, category1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + category1.getSubCategories().remove( subCategory1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 1 ) ); + assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 1 ) ); + assertTrue( category.getSubCategories().contains( subCategory2 ) ); + SubCategory subCategory = session.get( SubCategory.class, subCategory1.getId() ); + assertNull( subCategory ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyNoBackrefWithRemovedElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + Hibernate.initialize( category.getSubCategories() ); + return category; + } + ); + + category1_1.getSubCategories().remove( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 1 ) ); + assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 1 ) ); + assertTrue( category1.getSubCategories().contains( subCategory2 ) ); + SubCategory subCategory = session.get( SubCategory.class, subCategory1.getId() ); + assertNull( subCategory ); + } + ); + + cleanup( scope ); + } + + @SuppressWarnings({ "unchecked" }) + private void cleanup(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from SubItem" ).executeUpdate(); + for ( Hoarder hoarder : (List) session.createQuery( "from Hoarder" ).list() ) { + hoarder.getItems().clear(); + session.delete( hoarder ); + } + + for ( Category category : (List) session.createQuery( "from Category" ).list() ) { + if ( category.getExampleItem() != null ) { + category.setExampleItem( null ); + session.delete( category ); + } + } + + for ( Item item : (List) session.createQuery( "from Item" ).list() ) { + item.setCategory( null ); + session.delete( item ); + } + + session.createQuery( "delete from Item" ).executeUpdate(); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedTest.java new file mode 100644 index 0000000000..b0304498b0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesAllowedTest.java @@ -0,0 +1,1198 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.List; +import javax.persistence.PersistenceException; + +import org.hibernate.Hibernate; +import org.hibernate.StaleObjectStateException; +import org.hibernate.cfg.AvailableSettings; + +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.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + + +/** + * Tests merging multiple detached representations of the same entity when explicitly allowed. + * + * @author Gail Badner + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/Hoarder.hbm.xml" +) +@SessionFactory +@ServiceRegistry(settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "allow")) +public class MergeMultipleEntityCopiesAllowedTest { + + @Test + public void testNestedDiffBasicProperty(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // change basic property of nested entity + item1_1.setName( "item1_1 name" ); + + // change the nested Item to be the copy with the new name + item1.getCategory().setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the name from the top level item will win. + assertThat( item1Merged.getName(), is( item1.getName() ) ); + } + ); + + scope.inTransaction( + session -> { + Item item1Get = session.get( Item.class, item1.getId() ); + assertThat( item1Get.getName(), is( item1.getName() ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testNestedManyToOneChangedToNull(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // change many-to-one in nested entity to null. + item1_1.setCategory( null ); + item1.getCategory().setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the many-to-one from the top level item will win. + assertThat( item1Merged.getCategory().getName(), is( category.getName() ) ); + assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getCategory().getName(), is( category.getName() ) ); + assertSame( item, item.getCategory().getExampleItem() ); + } + ); + + cleanup( scope ); + } + + @Test + public void testNestedManyToOneChangedToNewEntity(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // change many-to-one in nested entity to a new (transient) value + Category categoryNew = new Category(); + categoryNew.setName( "new category" ); + item1_1.setCategory( categoryNew ); + item1.getCategory().setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the many-to-one from the top level item will win. + assertThat( item1Merged.getCategory().getName(), is( category.getName() ) ); + assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getCategory().getName(), is( category.getName() ) ); + assertSame( item, item.getCategory().getExampleItem() ); + // make sure new category got persisted + Category categoryQueried = (Category) session.createQuery( + "from Category c where c.name='new category'" ) + .uniqueResult(); + assertNotNull( categoryQueried ); + } + ); + + cleanup( scope ); + } + + @Test + public void testTopLevelManyToOneChangedToNewEntity(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // change many-to-one in top level to be a new (transient) + Category categoryNewer = new Category(); + categoryNewer.setName( "newer category" ); + item1.setCategory( categoryNewer ); + + // put the other representation in categoryNewer + categoryNewer.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the many-to-one from the top level item will win. + assertThat( item1Merged.getCategory().getName(), is( categoryNewer.getName() ) ); + assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getCategory().getName(), is( categoryNewer.getName() ) ); + assertSame( item, item.getCategory().getExampleItem() ); + // make sure original category is still there + Category categoryQueried = (Category) session.createQuery( "from Category c where c.name='category'" ) + .uniqueResult(); + assertNotNull( categoryQueried ); + // make sure original category has the same item. + assertSame( item, categoryQueried.getExampleItem() ); + // set exampleItem to null to avoid constraint violation on cleanup. + categoryQueried.setExampleItem( null ); + } + ); + + cleanup( scope ); + } + + @Test + public void testTopLevelManyToOneManagedNestedIsDetached(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + + item1Merged.setCategory( category ); + category.setExampleItem( item1_1 ); + + // now item1Merged is managed and it has a nested detached item + session.merge( item1Merged ); + assertThat( item1Merged.getCategory().getName(), is( category.getName() ) ); + assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getCategory().getName(), is( category.getName() ) ); + assertSame( item, item.getCategory().getExampleItem() ); + } + ); + + cleanup( scope ); + } + + @Test + public void testNestedValueCollectionWithChangedElements(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + item1.getColors().add( "red" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getColors() ); + return item; + } + ); + + scope.inTransaction( + session -> { + // add an element to collection in nested entity + item1_1.getColors().add( "blue" ); + item1.getCategory().setExampleItem( item1_1 ); + } + ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the collection from the top level item will win. + assertThat( item1Merged.getColors().size(), is( 1 ) ); + assertThat( item1Merged.getColors().iterator().next(), is( "red" ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getColors().size(), is( 1 ) ); + assertThat( item.getColors().iterator().next(), is( "red" ) ); + Hibernate.initialize( item.getCategory() ); + } + ); + + + // get another representation of item1 + Item item1_2 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getColors() ); + return item; + } + ); + + + // remove the existing elements from collection in nested entity + item1_2.getColors().clear(); + item1.getCategory().setExampleItem( item1_2 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the collection from the top level item will win. + assertThat( item1Merged.getColors().size(), is( 1 ) ); + assertThat( item1Merged.getColors().iterator().next(), is( "red" ) ); + } + ); + + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getColors().size(), is( 1 ) ); + assertThat( item.getColors().iterator().next(), is( "red" ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testTopValueCollectionWithChangedElements(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + item1.getColors().add( "red" ); + + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // add an element to collection in nested entity + item1.getColors().add( "blue" ); + item1.getCategory().setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // the collection from the top level item will win. + assertThat( item1Merged.getColors().size(), is( 2 ) ); + assertTrue( item1Merged.getColors().contains( "red" ) ); + assertTrue( item1Merged.getColors().contains( "blue" ) ); + } + ); + + Item item1_3 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getColors().size(), is( 2 ) ); + assertTrue( item.getColors().contains( "red" ) ); + assertTrue( item.getColors().contains( "blue" ) ); + Hibernate.initialize( item.getCategory() ); + return item; + } + ); + + // get another representation of item1 + Item item1_2 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // remove the existing elements from collection in nested entity + item1_3.getColors().clear(); + item1_3.getCategory().setExampleItem( item1_2 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1_3 ); + // the collection from the top level item will win. + assertTrue( item1Merged.getColors().isEmpty() ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1_3.getId() ); + assertTrue( item.getColors().isEmpty() ); + } + ); + + cleanup( scope ); + } + + @Test + public void testCascadeFromTransientToNonDirtyRepresentations(SessionFactoryScope scope) { + + Item item1 = new Item(); + item1.setName( "item1" ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // Get another representation of the same Item from a different session. + + Item item1_1 = scope.fromSession( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_1 ); + assertEquals( item1, item1_1 ); + + // Create a transient entity that references both representationsession. + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + hoarder.getItems().add( item1 ); + hoarder.setFavoriteItem( item1_1 ); + + Hoarder mergedHoarder = scope.fromTransaction( + session -> { + Hoarder mHoarder = (Hoarder) session.merge( hoarder ); + assertThat( mHoarder.getItems().size(), is( 1 ) ); + assertSame( mHoarder.getFavoriteItem(), mHoarder.getItems().iterator().next() ); + assertThat( mHoarder.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( mHoarder.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + return mHoarder; + } + ); + + scope.inTransaction( + session -> { + Hoarder h = (Hoarder) session.merge( mergedHoarder ); + assertThat( hoarder.getItems().size(), is( 1 ) ); + assertSame( h.getFavoriteItem(), h.getItems().iterator().next() ); + assertThat( h.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testCascadeFromDetachedToNonDirtyRepresentations(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1" ); + + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + + scope.inTransaction( + session -> { + session.persist( item1 ); + session.persist( hoarder ); + } + ); + + // Get another representation of the same Item from a different session. + + Item item1_1 = scope.fromSession( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_1 ); + assertEquals( item1, item1_1 ); + + // Update hoarder (detached) to references both representationsession. + hoarder.getItems().add( item1 ); + hoarder.setFavoriteItem( item1_1 ); + + Hoarder mergedHoarder = scope.fromTransaction( + session -> { + Hoarder h = (Hoarder) session.merge( hoarder ); + assertThat( h.getItems().size(), is( 1 ) ); + assertSame( h.getFavoriteItem(), h.getItems().iterator().next() ); + assertThat( h.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + return h; + } + ); + + scope.inTransaction( + session -> { + Hoarder h = (Hoarder) session.merge( mergedHoarder ); + assertThat( h.getItems().size(), is( 1 ) ); + assertSame( h.getFavoriteItem(), h.getItems().iterator().next() ); + assertThat( h.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testCascadeFromDetachedToGT2DirtyRepresentations(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1" ); + Category category1 = new Category(); + category1.setName( "category1" ); + item1.setCategory( category1 ); + + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + + scope.inTransaction( + session -> { + session.persist( item1 ); + session.persist( hoarder ); + } + ); + + // Get another representation of the same Item from a different session. + + Item item1_1 = scope.fromSession( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1 and item1_1 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_1 ); + assertEquals( item1, item1_1 ); + + // Get another representation of the same Item from a different session. + + Item item1_2 = scope.fromSession( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_2 ); + assertEquals( item1, item1_2 ); + + item1_1.setName( "item1_1" ); + item1_2.setName( "item1_2" ); + + // Update hoarder (detached) to references both representationsession. + item1.getCategory().setExampleItem( item1_2 ); + hoarder.getItems().add( item1 ); + hoarder.setFavoriteItem( item1_1 ); + hoarder.getFavoriteItem().getCategory(); + + Hoarder mergedHoarder = scope.fromTransaction( + session -> { + Hoarder mHoarder = (Hoarder) session.merge( hoarder ); + assertThat( mHoarder.getItems().size(), is( 1 ) ); + assertSame( mHoarder.getFavoriteItem(), mHoarder.getItems().iterator().next() ); + assertSame( mHoarder.getFavoriteItem(), mHoarder.getFavoriteItem().getCategory().getExampleItem() ); + assertThat( mHoarder.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( mHoarder.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + assertThat( mHoarder.getFavoriteItem().getName(), is( item1.getName() ) ); + return mHoarder; + } + ); + + scope.inTransaction( + session -> { + Hoarder h = (Hoarder) session.merge( mergedHoarder ); + assertThat( h.getItems().size(), is( 1 ) ); + assertSame( h.getFavoriteItem(), h.getItems().iterator().next() ); + assertSame( h.getFavoriteItem(), h.getFavoriteItem().getCategory().getExampleItem() ); + assertThat( h.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testTopLevelEntityNewerThanNested(SessionFactoryScope scope) { + Item item = new Item(); + item.setName( "item" ); + + Category category = new Category(); + category.setName( "category" ); + + scope.inTransaction( + session -> { + session.persist( item ); + session.persist( category ); + } + ); + + // Get the Category from a different session. + Category category1_2 = scope.fromTransaction( + session -> + session.get( Category.class, category.getId() ) + ); + + // Get and update the same Category. + Category category1_1 = scope.fromTransaction( + session -> { + Category category1 = session.get( Category.class, category.getId() ); + category1.setName( "new name" ); + return category1; + } + ); + + assertTrue( category1_2.getVersion() < category1_1.getVersion() ); + + category1_1.setExampleItem( item ); + item.setCategory( category1_2 ); + + scope.inTransaction( + session -> { + try { + // representation merged at top level is newer than nested representation. + session.merge( category1_1 ); + fail( "should have failed because one representation is an older version." ); + } + catch (PersistenceException e) { + // expected + assertTyping( StaleObjectStateException.class, e.getCause() ); + } + } + ); + + cleanup( scope ); + } + + @Test + public void testNestedEntityNewerThanTopLevel(SessionFactoryScope scope) { + Item item = new Item(); + item.setName( "item" ); + + Category category = new Category(); + category.setName( "category" ); + + scope.inTransaction( + session -> { + session.persist( item ); + session.persist( category ); + } + ); + + // Get category1_1 from a different session. + Category category1_1 = scope.fromSession( + session -> + session.get( Category.class, category.getId() ) + ); + + // Get and update category1_2 to increment its version. + Category category1_2 = scope.fromTransaction( + session -> { + Category category1 = session.get( Category.class, category.getId() ); + category1.setName( "new name" ); + return category1; + } + ); + + assertTrue( category1_2.getVersion() > category1_1.getVersion() ); + + category1_1.setExampleItem( item ); + item.setCategory( category1_2 ); + + scope.inTransaction( + session -> { + try { + // nested representation is newer than top lever representation. + session.merge( category1_1 ); + fail( "should have failed because one representation is an older version." ); + } + catch (PersistenceException e) { + // expected + assertTyping( StaleObjectStateException.class, e.getCause() ); + } + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9240") + public void testTopLevelUnidirOneToManyBackrefWithNewElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); + + Category category = new Category(); + category.setName( "category" ); + + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + // The following will fail due to PropertyValueException because item1 will + // be removed from the inverted merge map when the operation cascades to item1_1. + Item item1Merged = (Item) session.merge( item1 ); + // top-level collection should win + assertThat( item1.getSubItemsBackref().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyBackrefWithNewElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getSubItemsBackref() ); + return item; + } + ); + + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1_1.getSubItemsBackref().add( subItem2 ); + + category.setExampleItem( item1_1 ); + + Item item1Merged = scope.fromTransaction( + session -> { + Item item = (Item) session.merge( item1 ); + // The resulting collection should contain the added element + assertThat( item.getSubItemsBackref().size(), is( 2 ) ); + assertThat( item.getSubItemsBackref().get( 0 ).getName(), is( "subItem1 name" ) ); + assertThat( item.getSubItemsBackref().get( 1 ).getName(), is( "subItem2 name" ) ); + return item; + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 2 ) ); + assertThat( item.getSubItemsBackref().get( 0 ).getName(), is( "subItem1 name" ) ); + assertThat( item1Merged.getSubItemsBackref().get( 1 ).getName(), is( "subItem2 name" ) ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyBackrefWithRemovedElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); + + Category category = new Category(); + category.setName( "category" ); + + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + // remove subItem1 from top-level Item + item1.getSubItemsBackref().remove( subItem1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // entity should have been removed + assertThat( item1Merged.getSubItemsBackref().size(), is( 1 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 1 ) ); + SubItem subItem = session.get( SubItem.class, subItem1.getId() ); + // cascade does not include delete-orphan, so subItem1 should still be persistent. + assertNotNull( subItem ); + } + ); + + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyBackrefWithRemovedElement(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + SubItem subItem1 = new SubItem(); + subItem1.setName( "subItem1 name" ); + item1.getSubItemsBackref().add( subItem1 ); + SubItem subItem2 = new SubItem(); + subItem2.setName( "subItem2 name" ); + item1.getSubItemsBackref().add( subItem2 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + Hibernate.initialize( item.getSubItemsBackref() ); + return item; + } + ); + + // remove subItem1 from the nested Item + item1_1.getSubItemsBackref().remove( subItem1 ); + + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + category.setExampleItem( item1_1 ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + // entity should have been removed + assertThat( item1Merged.getSubItemsBackref().size(), is( 1 ) ); + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getSubItemsBackref().size(), is( 1 ) ); + SubItem subItem = session.get( SubItem.class, subItem1.getId() ); + // cascade does not include delete-orphan, so subItem1 should still be persistent. + assertNotNull( subItem ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyNoBackrefWithNewElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> + session.get( Category.class, category1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); + + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category = (Category) session.merge( category1 ); + assertThat( category.getSubCategories().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyNoBackrefWithNewElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + Hibernate.initialize( category.getSubCategories() ); + return category; + } + ); + + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1_1.getSubCategories().add( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 2 ) ); + } + ); + + cleanup( scope ); + } + + @Test + //@FailureExpected( jiraKey = "HHH-9106" ) + public void testTopLevelUnidirOneToManyNoBackrefWithRemovedElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> + session.get( Category.class, category1.getId() ) + ); + + assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + category1.getSubCategories().remove( subCategory1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 1 ) ); + assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 1 ) ); + assertTrue( category.getSubCategories().contains( subCategory2 ) ); + // cascade does not include delete-orphan, so subCategory1 should still be persistent. + SubCategory subCategory = session.get( SubCategory.class, subCategory1.getId() ); + assertNotNull( subCategory ); + } + ); + + cleanup( scope ); + } + + @Test + @FailureExpected(jiraKey = "HHH-9239") + public void testNestedUnidirOneToManyNoBackrefWithRemovedElement(SessionFactoryScope scope) { + Category category1 = new Category(); + category1.setName( "category1 name" ); + SubCategory subCategory1 = new SubCategory(); + subCategory1.setName( "subCategory1 name" ); + category1.getSubCategories().add( subCategory1 ); + SubCategory subCategory2 = new SubCategory(); + subCategory2.setName( "subCategory2 name" ); + category1.getSubCategories().add( subCategory2 ); + + scope.inTransaction( + session -> + session.persist( category1 ) + ); + + // get another representation of category1 + Category category1_1 = scope.fromTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + Hibernate.initialize( category.getSubCategories() ); + return category; + } + ); + + category1_1.getSubCategories().remove( subCategory2 ); + + Item item = new Item(); + item.setName( "item" ); + category1.setExampleItem( item ); + item.setCategory( category1_1 ); + + scope.inTransaction( + session -> { + Category category1Merged = (Category) session.merge( category1 ); + assertThat( category1Merged.getSubCategories().size(), is( 1 ) ); + assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); + } + ); + + scope.inTransaction( + session -> { + Category category = session.get( Category.class, category1.getId() ); + assertThat( category.getSubCategories().size(), is( 1 ) ); + assertTrue( category.getSubCategories().contains( subCategory2 ) ); + // cascade does not include delete-orphan, so subCategory1 should still be persistent. + SubCategory subCategory = session.get( SubCategory.class, subCategory1.getId() ); + assertNotNull( subCategory ); + } + ); + + cleanup( scope ); + } + + @SuppressWarnings({ "unchecked" }) + private void cleanup(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from SubItem" ).executeUpdate(); + for ( Hoarder hoarder : (List) session.createQuery( "from Hoarder" ).list() ) { + hoarder.getItems().clear(); + session.delete( hoarder ); + } + + for ( Category category : (List) session.createQuery( "from Category" ).list() ) { + Item exampleItem = category.getExampleItem(); + if ( exampleItem != null ) { + category.setExampleItem( null ); + exampleItem.setCategory( null ); + session.delete( category ); + session.delete( exampleItem ); + } + } + + for ( Item item : (List) session.createQuery( "from Item" ).list() ) { + Category category = item.getCategory(); + item.setCategory( null ); + if ( category != null ) { + category.setExampleItem( null ); + } + session.delete( item ); + } + + session.createQuery( "delete from Item" ).executeUpdate(); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesCustomTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesCustomTest.java new file mode 100644 index 0000000000..4b535c2e74 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesCustomTest.java @@ -0,0 +1,193 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.cfg.AvailableSettings; + +import org.hibernate.testing.TestForIssue; +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.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * Tests merging multiple detached representations of the same entity using a custom EntityCopyObserver. + * + * @author Gail Badner + */ +@TestForIssue(jiraKey = "HHH-9106") +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/Hoarder.hbm.xml", + annotatedClasses = { + Category.class, + Hoarder.class, + Item.class + } +) +@SessionFactory +@ServiceRegistry( + settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "org.hibernate.orm.test.ops.CustomEntityCopyObserver") +) +public class MergeMultipleEntityCopiesCustomTest { + + @Test + public void testMergeMultipleEntityCopiesAllowed(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1" ); + + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + + scope.inTransaction( + session -> { + session.persist( item1 ); + session.persist( hoarder ); + } + ); + + // Get another representation of the same Item. + + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_1 ); + assertEquals( item1, item1_1 ); + + // Update hoarder (detached) to references both representations. + hoarder.getItems().add( item1 ); + hoarder.setFavoriteItem( item1_1 ); + + Hoarder h = scope.fromTransaction( + session -> { + // the merge should succeed because it does not have Category copies. + // (CustomEntityCopyObserver does not allow Category copies; it does allow Item copies) + Hoarder h1 = (Hoarder) session.merge( hoarder ); + assertThat( h1.getItems().size(), is( 1 ) ); + assertSame( h1.getFavoriteItem(), h1.getItems().iterator().next() ); + assertThat( h1.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h1.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + return h1; + } + ); + + scope.inTransaction( + session -> { + Hoarder h1 = session.get( Hoarder.class, h.getId() ); + assertThat( h1.getItems().size(), is( 1 ) ); + assertSame( h1.getFavoriteItem(), h1.getItems().iterator().next() ); + assertThat( h1.getFavoriteItem().getId(), is( item1.getId() ) ); + assertThat( h1.getFavoriteItem().getCategory(), is( item1.getCategory() ) ); + } + ); + + cleanup( scope ); + } + + @Test + public void testMergeMultipleEntityCopiesAllowedAndDisallowed(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + // make sure item1_1.category is initialized + Hibernate.initialize( item.getCategory() ); + return item; + } + ); + + scope.inSession( + session -> { + session.beginTransaction(); + Item item1Merged = (Item) session.merge( item1 ); + + item1Merged.setCategory( category ); + category.setExampleItem( item1_1 ); + + // now item1Merged is managed and it has a nested detached item + // and there is multiple managed/detached Category objects + try { + // the following should fail because multiple copies of Category objects is not allowed by + // CustomEntityCopyObserver + session.merge( item1Merged ); + fail( "should have failed because CustomEntityCopyObserver does not allow multiple copies of a Category. " ); + } + catch (IllegalStateException ex) { + //expected + } + finally { + if ( session.getTransaction().isActive() ) { + session.getTransaction().rollback(); + } + } + } + ); + + scope.inTransaction( + session -> { + Item item = session.get( Item.class, item1.getId() ); + assertThat( item.getCategory().getName(), is( category.getName() ) ); + assertSame( item, item.getCategory().getExampleItem() ); + } + ); + + cleanup( scope ); + } + + @SuppressWarnings({ "unchecked" }) + private void cleanup(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + for ( Hoarder hoarder : (List) session.createQuery( "from Hoarder" ).list() ) { + hoarder.getItems().clear(); + session.delete( hoarder ); + } + + for ( Category category : (List) session.createQuery( "from Category" ).list() ) { + if ( category.getExampleItem() != null ) { + category.setExampleItem( null ); + session.delete( category ); + } + } + + for ( Item item : (List) session.createQuery( "from Item" ).list() ) { + item.setCategory( null ); + session.delete( item ); + } + + session.createQuery( "delete from Item" ).executeUpdate(); + } + ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java new file mode 100644 index 0000000000..b2dc67793c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.List; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * Tests merging multiple detached representations of the same entity using + * a the default (that does not allow this). + * + * @author Gail Badner + */ +@TestForIssue(jiraKey = "HHH-9106") +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/Hoarder.hbm.xml" +) +@SessionFactory +public class MergeMultipleEntityCopiesDisallowedByDefaultTest { + + @Test + public void testCascadeFromDetachedToNonDirtyRepresentations(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1" ); + + Hoarder hoarder = new Hoarder(); + hoarder.setName( "joe" ); + + scope.inTransaction( + session -> { + session.persist( item1 ); + session.persist( hoarder ); + } + ); + + // Get another representation of the same Item from a different session. + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + // item1_1 and item1_2 are unmodified representations of the same persistent entity. + assertNotSame( item1, item1_1 ); + assertEquals( item1, item1_1 ); + + // Update hoarder (detached) to references both representations. + hoarder.getItems().add( item1 ); + hoarder.setFavoriteItem( item1_1 ); + + scope.inTransaction( + session -> { + try { + session.merge( hoarder ); + fail( "should have failed due IllegalStateException" ); + } + catch (IllegalStateException ex) { + //expected + } + } + ); + + cleanup( scope ); + } + + @Test + public void testTopLevelManyToOneManagedNestedIsDetached(SessionFactoryScope scope) { + Item item1 = new Item(); + item1.setName( "item1 name" ); + Category category = new Category(); + category.setName( "category" ); + item1.setCategory( category ); + category.setExampleItem( item1 ); + + scope.inTransaction( + session -> + session.persist( item1 ) + ); + + // get another representation of item1 + Item item1_1 = scope.fromTransaction( + session -> + session.get( Item.class, item1.getId() ) + ); + + scope.inTransaction( + session -> { + Item item1Merged = (Item) session.merge( item1 ); + + item1Merged.setCategory( category ); + category.setExampleItem( item1_1 ); + + // now item1Merged is managed and it has a nested detached item + try { + session.merge( item1Merged ); + fail( "should have failed due IllegalStateException" ); + } + catch (IllegalStateException ex) { + //expected + } + } + ); + + cleanup( scope ); + } + + @SuppressWarnings({ "unchecked" }) + private void cleanup(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from SubItem" ).executeUpdate(); + for ( Hoarder hoarder : (List) session.createQuery( "from Hoarder" ).list() ) { + hoarder.getItems().clear(); + session.delete( hoarder ); + } + + for ( Category category : (List) session.createQuery( "from Category" ).list() ) { + if ( category.getExampleItem() != null ) { + category.setExampleItem( null ); + session.delete( category ); + } + } + + for ( Item item : (List) session.createQuery( "from Item" ).list() ) { + item.setCategory( null ); + session.delete( item ); + } + + session.createQuery( "delete from Item" ).executeUpdate(); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedTest.java similarity index 61% rename from hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedTest.java index a2df70736e..18d8e67a01 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeMultipleEntityCopiesDisallowedTest.java @@ -4,11 +4,13 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; -import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.Setting; /** @@ -16,14 +18,9 @@ import org.hibernate.testing.TestForIssue; * * @author Gail Badner */ -@TestForIssue( jiraKey = "HHH-9106") +@TestForIssue(jiraKey = "HHH-9106") +@ServiceRegistry( + settings = @Setting(name = AvailableSettings.MERGE_ENTITY_COPY_OBSERVER, value = "disallow") +) public class MergeMultipleEntityCopiesDisallowedTest extends MergeMultipleEntityCopiesDisallowedByDefaultTest { - - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( - "hibernate.event.merge.entity_copy_observer", - "disallow" - ); - } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeTest.java new file mode 100755 index 0000000000..125d6d388b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/MergeTest.java @@ -0,0 +1,850 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.persistence.PersistenceException; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.hibernate.Hibernate; +import org.hibernate.NonUniqueObjectException; +import org.hibernate.Session; +import org.hibernate.StaleObjectStateException; +import org.hibernate.dialect.AbstractHANADialect; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Gavin King + */ +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsNoColumnInsert.class) +public class MergeTest extends AbstractOperationTestCase { + + @Test + public void testMergeStaleVersionFails(SessionFactoryScope scope) { + VersionedEntity entity = new VersionedEntity( "entity", "entity" ); + scope.inTransaction( + session -> + session.persist( entity ) + ); + + // make the detached 'entity' reference stale... + scope.inTransaction( + session -> { + VersionedEntity entity2 = session.get( VersionedEntity.class, entity.getId() ); + entity2.setName( "entity-name" ); + } + ); + + // now try to reattach it + scope.inSession( + session -> { + try { + session.beginTransaction(); + session.merge( entity ); + session.getTransaction().commit(); + fail( "was expecting staleness error" ); + } + catch (PersistenceException e) { + // expected + assertTyping( StaleObjectStateException.class, e.getCause() ); + } + finally { + if ( session.getTransaction().isActive() ) { + session.getTransaction().rollback(); + } + } + } + ); + } + + @Test + public void testMergeBidiPrimayKeyOneToOne(SessionFactoryScope scope) { +// scope.getSessionFactory().close(); + Person p = new Person( "steve" ); + scope.inTransaction( + session -> { + new PersonalDetails( "I have big feet", p ); + session.persist( p ); + } + ); + + clearCounts( scope ); + + p.getDetails().setSomePersonalDetail( p.getDetails().getSomePersonalDetail() + " and big hands too" ); + + Person person = scope.fromTransaction( + session -> + (Person) session.merge( p ) + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 1, scope ); + assertDeleteCount( 0, scope ); + + scope.inTransaction( + session -> + session.delete( person ) + ); + } + + @Test + public void testMergeBidiForeignKeyOneToOne(SessionFactoryScope scope) { + Person p = new Person( "steve" ); + Address a = new Address( "123 Main", "Austin", "US", p ); + scope.inTransaction( + session -> { + new PersonalDetails( "I have big feet", p ); + session.persist( a ); + session.persist( p ); + } + ); + + clearCounts( scope ); + + p.getAddress().setStreetAddress( "321 Main" ); + Person person = scope.fromTransaction( + session -> + (Person) session.merge( p ) + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); // no cascade + assertDeleteCount( 0, scope ); + + scope.inTransaction( + session -> { + session.delete( a ); + session.delete( person ); + } + ); + } + + @Test + public void testNoExtraUpdatesOnMerge(SessionFactoryScope scope) { + Node node = new Node( "test" ); + scope.inTransaction( + session -> + session.persist( node ) + ); + + clearCounts( scope ); + + // node is now detached, but we have made no changes. so attempt to merge it + // into this new session; this should cause no updates... + Node n = (Node) scope.fromTransaction( + session -> + session.merge( node ) + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + + /////////////////////////////////////////////////////////////////////// + // as a control measure, now update the node while it is detached and + // make sure we get an update as a result... + n.setDescription( "new description" ); + + scope.inTransaction( + session -> + session.merge( n ) + ); + + assertUpdateCount( 1, scope ); + assertInsertCount( 0, scope ); + /////////////////////////////////////////////////////////////////////// + + cleanup( scope ); + } + + @Test + @SuppressWarnings({ "unchecked" }) + public void testNoExtraUpdatesOnMergeWithCollection(SessionFactoryScope scope) { + Node parent = new Node( "parent" ); + scope.inTransaction( + session -> { + Node child = new Node( "child" ); + parent.getChildren().add( child ); + child.setParent( parent ); + session.persist( parent ); + } + ); + + clearCounts( scope ); + + // parent is now detached, but we have made no changes. so attempt to merge it + // into this new session; this should cause no updates... + Node p = scope.fromTransaction( + session -> + (Node) session.merge( parent ) + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + + /////////////////////////////////////////////////////////////////////// + // as a control measure, now update the node while it is detached and + // make sure we get an update as a result... + ( (Node) p.getChildren().iterator().next() ).setDescription( "child's new description" ); + p.addChild( new Node( "second child" ) ); + scope.inTransaction( + session -> + session.merge( p ) + ); + assertUpdateCount( 1, scope ); + assertInsertCount( 1, scope ); + /////////////////////////////////////////////////////////////////////// + + cleanup( scope ); + } + + @Test + public void testNoExtraUpdatesOnMergeVersioned(SessionFactoryScope scope) { + VersionedEntity entity = new VersionedEntity( "entity", "entity" ); + scope.inTransaction( + session -> + session.persist( entity ) + ); + + clearCounts( scope ); + + // entity is now detached, but we have made no changes. so attempt to merge it + // into this new session; this should cause no updates... + VersionedEntity mergedEntity = scope.fromTransaction( + session -> + (VersionedEntity) session.merge( entity ) + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + assertThat( "unexpected version increment", mergedEntity.getVersion(), is( entity.getVersion() ) ); + + + /////////////////////////////////////////////////////////////////////// + // as a control measure, now update the node while it is detached and + // make sure we get an update as a result... + entity.setName( "new name" ); + + scope.inTransaction( + session -> + session.merge( entity ) + ); + assertUpdateCount( 1, scope ); + assertInsertCount( 0, scope ); + /////////////////////////////////////////////////////////////////////// + + cleanup( scope ); + } + + @Test + @SuppressWarnings({ "unchecked" }) + public void testNoExtraUpdatesOnMergeVersionedWithCollection(SessionFactoryScope scope) { + VersionedEntity parent = new VersionedEntity( "parent", "parent" ); + VersionedEntity child = new VersionedEntity( "child", "child" ); + scope.inTransaction( + session -> { + parent.getChildren().add( child ); + child.setParent( parent ); + session.persist( parent ); + } + ); + + clearCounts( scope ); + + // parent is now detached, but we have made no changes. so attempt to merge it + // into this new session; this should cause no updates... + VersionedEntity mergedParent = + + scope.fromTransaction( + session -> + (VersionedEntity) session.merge( parent ) + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + assertThat( "unexpected parent version increment", mergedParent.getVersion(), is( parent.getVersion() ) ); + VersionedEntity mergedChild = (VersionedEntity) mergedParent.getChildren().iterator().next(); + assertThat( "unexpected child version increment", mergedChild.getVersion(), is( child.getVersion() ) ); + + /////////////////////////////////////////////////////////////////////// + // as a control measure, now update the node while it is detached and + // make sure we get an update as a result... + mergedParent.setName( "new name" ); + mergedParent.getChildren().add( new VersionedEntity( "child2", "new child" ) ); + + scope.inTransaction( + session -> + session.merge( mergedParent ) + ); + + assertUpdateCount( 1, scope ); + assertInsertCount( 1, scope ); + /////////////////////////////////////////////////////////////////////// + + cleanup( scope ); + } + + @Test + @SuppressWarnings({ "unchecked", "UnusedAssignment", "UnusedDeclaration" }) + public void testNoExtraUpdatesOnPersistentMergeVersionedWithCollection(SessionFactoryScope scope) { + VersionedEntity parent = new VersionedEntity( "parent", "parent" ); + VersionedEntity child = new VersionedEntity( "child", "child" ); + scope.inTransaction( + session -> { + parent.getChildren().add( child ); + child.setParent( parent ); + session.persist( parent ); + } + ); + + clearCounts( scope ); + + // parent is now detached, but we have made no changes. so attempt to merge it + // into this new session; this should cause no updates... + VersionedEntity mergedParent = scope.fromTransaction( + session -> { + // load parent so that merge will follow entityIsPersistent path + VersionedEntity persistentParent = session.get( + VersionedEntity.class, + parent.getId() + ); + // load children + VersionedEntity persistentChild = (VersionedEntity) persistentParent.getChildren() + .iterator() + .next(); + return (VersionedEntity) session.merge( persistentParent ); // <-- This merge leads to failure + } + ); + + assertUpdateCount( 0, scope ); + assertInsertCount( 0, scope ); + assertThat( "unexpected parent version increment", mergedParent.getVersion(), is( parent.getVersion() ) ); + VersionedEntity mergedChild = (VersionedEntity) mergedParent.getChildren().iterator().next(); + assertThat( "unexpected child version increment", mergedChild.getVersion(), is( child.getVersion() ) ); + + /////////////////////////////////////////////////////////////////////// + // as a control measure, now update the node once it is loaded and + // make sure we get an update as a result... + scope.inTransaction( + session -> { + VersionedEntity persistentParent = session.get( + VersionedEntity.class, + parent.getId() + ); + persistentParent.setName( "new name" ); + persistentParent.getChildren().add( new VersionedEntity( "child2", "new child" ) ); + persistentParent = (VersionedEntity) session.merge( persistentParent ); + + } + ); + assertUpdateCount( 1, scope ); + assertInsertCount( 1, scope ); + /////////////////////////////////////////////////////////////////////// + + // cleanup(); + } + + @Test + public void testPersistThenMergeInSameTxnWithVersion(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + + VersionedEntity entity = new VersionedEntity( "test", "test" ); + session.persist( entity ); + session.merge( new VersionedEntity( "test", "test-2" ) ); + + try { + // control operation... + session.saveOrUpdate( new VersionedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch (NonUniqueObjectException expected) { + // expected behavior + } + } + ); + + cleanup( scope ); + } + + @Test + public void testPersistThenMergeInSameTxnWithTimestamp(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + TimestampedEntity entity = new TimestampedEntity( "test", "test" ); + session.persist( entity ); + session.merge( new TimestampedEntity( "test", "test-2" ) ); + + try { + // control operation... + session.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch (NonUniqueObjectException expected) { + // expected behavior + } + } + ); + + cleanup( scope ); + } + + @Test + public void testMergeDeepTree(SessionFactoryScope scope) { + clearCounts( scope ); + + Node root = new Node( "root" ); + Node grandchild = new Node( "grandchild" ); + Node child = new Node( "child" ); + scope.inTransaction( + session -> { + root.addChild( child ); + child.addChild( grandchild ); + session.merge( root ); + } + ); + + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + grandchild.setDescription( "the grand child" ); + Node grandchild2 = new Node( "grandchild2" ); + child.addChild( grandchild2 ); + + scope.inTransaction( + session -> + session.merge( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 1, scope ); + clearCounts( scope ); + + Node child2 = new Node( "child2" ); + Node grandchild3 = new Node( "grandchild3" ); + child2.addChild( grandchild3 ); + root.addChild( child2 ); + + scope.inTransaction( + session -> + session.merge( root ) + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> { + session.delete( grandchild ); + session.delete( grandchild2 ); + session.delete( grandchild3 ); + session.delete( child ); + session.delete( child2 ); + session.delete( root ); + } + ); + } + + @Test + public void testMergeDeepTreeWithGeneratedId(SessionFactoryScope scope) { + clearCounts( scope ); + + NumberedNode root = scope.fromTransaction( + session -> { + NumberedNode r = new NumberedNode( "root" ); + NumberedNode child = new NumberedNode( "child" ); + NumberedNode grandchild = new NumberedNode( "grandchild" ); + r.addChild( child ); + child.addChild( grandchild ); + return (NumberedNode) session.merge( r ); + } + ); + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + NumberedNode child = (NumberedNode) root.getChildren().iterator().next(); + NumberedNode grandchild = (NumberedNode) child.getChildren().iterator().next(); + grandchild.setDescription( "the grand child" ); + NumberedNode grandchild2 = new NumberedNode( "grandchild2" ); + child.addChild( grandchild2 ); + + NumberedNode node = scope.fromTransaction( + session -> + (NumberedNode) session.merge( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 1, scope ); + clearCounts( scope ); + + scope.getSessionFactory().getCache().evictEntityRegion( NumberedNode.class ); + + NumberedNode child2 = new NumberedNode( "child2" ); + NumberedNode grandchild3 = new NumberedNode( "grandchild3" ); + child2.addChild( grandchild3 ); + node.addChild( child2 ); + + scope.inTransaction( + session -> + session.merge( node ) + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> { + session.createQuery( "delete from NumberedNode where name like 'grand%'" ).executeUpdate(); + session.createQuery( "delete from NumberedNode where name like 'child%'" ).executeUpdate(); + session.createQuery( "delete from NumberedNode" ).executeUpdate(); + } + ); + } + + @Test + public void testMergeTree(SessionFactoryScope scope) { + clearCounts( scope ); + + Node root = new Node( "root" ); + Node child = new Node( "child" ); + scope.inTransaction( + session -> { + root.addChild( child ); + session.persist( root ); + } + ); + + assertInsertCount( 2, scope ); + clearCounts( scope ); + + root.setDescription( "The root node" ); + child.setDescription( "The child node" ); + + Node secondChild = new Node( "second child" ); + + root.addChild( secondChild ); + + scope.inTransaction( + session -> + session.merge( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 2, scope ); + + cleanup( scope ); + } + + @Test + public void testMergeTreeWithGeneratedId(SessionFactoryScope scope) { + clearCounts( scope ); + + NumberedNode root = new NumberedNode( "root" ); + NumberedNode child = new NumberedNode( "child" ); + + scope.inTransaction( + session -> { + root.addChild( child ); + session.persist( root ); + } + ); + + assertInsertCount( 2, scope ); + clearCounts( scope ); + + root.setDescription( "The root node" ); + child.setDescription( "The child node" ); + + NumberedNode secondChild = new NumberedNode( "second child" ); + + root.addChild( secondChild ); + + scope.inTransaction( + session -> + session.merge( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 2, scope ); + + cleanup( scope ); + } + + @Test + public void testMergeManaged(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + NumberedNode root = new NumberedNode( "root" ); + session.persist( root ); + session.getTransaction().commit(); + + clearCounts( scope ); + + session.beginTransaction(); + NumberedNode child = new NumberedNode( "child" ); + root.addChild( child ); + assertSame( root, session.merge( root ) ); + Object mergedChild = root.getChildren().iterator().next(); + assertNotSame( mergedChild, child ); + assertTrue( session.contains( mergedChild ) ); + assertFalse( session.contains( child ) ); + assertThat( root.getChildren().size(), is( 1 ) ); + assertTrue( root.getChildren().contains( mergedChild ) ); + //assertNotSame( mergedChild, s.merge(child) ); //yucky :( + session.getTransaction().commit(); + + assertInsertCount( 1, scope ); + assertUpdateCount( 0, scope ); + + assertThat( root.getChildren().size(), is( 1 ) ); + assertTrue( root.getChildren().contains( mergedChild ) ); + + session.beginTransaction(); + assertThat( + getNumneredNodeRowCount( session ), + is( 2L ) + ); + } + ); + + cleanup( scope ); + } + + private Long getNumneredNodeRowCount(Session s) { + CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); + CriteriaQuery criteria = criteriaBuilder.createQuery( Long.class ); + Root root = criteria.from( NumberedNode.class ); + criteria.select( criteriaBuilder.count( root ) ); + return s.createQuery( criteria ).uniqueResult(); + } + + @Test + public void testMergeManagedUninitializedCollection(SessionFactoryScope scope) { + NumberedNode root = new NumberedNode( "root" ); + scope.inTransaction( + session -> { + root.addChild( new NumberedNode( "child" ) ); + session.persist( root ); + } + ); + + clearCounts( scope ); + + NumberedNode newRoot = new NumberedNode( "root" ); + newRoot.setId( root.getId() ); + + scope.inTransaction( + session -> { + NumberedNode r = session.get( NumberedNode.class, root.getId() ); + Set managedChildren = r.getChildren(); + assertFalse( Hibernate.isInitialized( managedChildren ) ); + newRoot.setChildren( managedChildren ); + assertSame( r, session.merge( newRoot ) ); + assertSame( managedChildren, r.getChildren() ); + assertFalse( Hibernate.isInitialized( managedChildren ) ); + session.getTransaction().commit(); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 0, scope ); + + session.beginTransaction(); + assertThat( + getNumneredNodeRowCount( session ), + is( 2L ) + ); + } + ); + + cleanup( scope ); + } + + @Test + public void testMergeManagedInitializedCollection(SessionFactoryScope scope) { + NumberedNode r = new NumberedNode( "root" ); + scope.inTransaction( + session -> { + r.addChild( new NumberedNode( "child" ) ); + session.persist( r ); + } + ); + + clearCounts( scope ); + + NumberedNode newRoot = new NumberedNode( "root" ); + newRoot.setId( r.getId() ); + + scope.inTransaction( + session -> { + NumberedNode root = session.get( NumberedNode.class, r.getId() ); + Set managedChildren = root.getChildren(); + Hibernate.initialize( managedChildren ); + assertTrue( Hibernate.isInitialized( managedChildren ) ); + newRoot.setChildren( managedChildren ); + assertSame( root, session.merge( newRoot ) ); + assertSame( managedChildren, root.getChildren() ); + assertTrue( Hibernate.isInitialized( managedChildren ) ); + session.getTransaction().commit(); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 0, scope ); + + session.beginTransaction(); + assertThat( + getNumneredNodeRowCount( session ), + is( 2L ) + ); + } + ); + + cleanup( scope ); + } + + @Test + @SuppressWarnings({ "unchecked" }) + @SkipForDialect(dialectClass = AbstractHANADialect.class, reason = " HANA doesn't support tables consisting of only a single auto-generated column") + public void testRecursiveMergeTransient(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Employer jboss = new Employer(); + Employee gavin = new Employee(); + jboss.setEmployees( new ArrayList() ); + jboss.getEmployees().add( gavin ); + session.merge( jboss ); + session.flush(); + jboss = (Employer) session.createQuery( "from Employer e join fetch e.employees" ).uniqueResult(); + assertTrue( Hibernate.isInitialized( jboss.getEmployees() ) ); + assertThat( jboss.getEmployees().size(), is( 1 ) ); + session.clear(); + session.merge( jboss.getEmployees().iterator().next() ); + } + ); + + cleanup( scope ); + } + + @Test + public void testDeleteAndMerge(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Employer jboss = new Employer(); + session.persist( jboss ); + session.getTransaction().commit(); + session.clear(); + + session.getTransaction().begin(); + Employer otherJboss; + otherJboss = session.get( Employer.class, jboss.getId() ); + session.delete( otherJboss ); + session.getTransaction().commit(); + session.clear(); + jboss.setVers( 1 ); + session.getTransaction().begin(); + session.merge( jboss ); + } + ); + + cleanup( scope ); + } + + @SuppressWarnings({ "unchecked" }) + @Test + @SkipForDialect(dialectClass = AbstractHANADialect.class, reason = " HANA doesn't support tables consisting of only a single auto-generated column") + public void testMergeManyToManyWithCollectionDeference(SessionFactoryScope scope) { + // setup base data... + Competition competition = new Competition(); + scope.inTransaction( + session -> { + competition.getCompetitors().add( new Competitor( "Name" ) ); + competition.getCompetitors().add( new Competitor() ); + competition.getCompetitors().add( new Competitor() ); + session.persist( competition ); + } + ); + + // the competition graph is now detached: + // 1) create a new List reference to represent the competitors + Competition competition2 = scope.fromTransaction( + session -> { + List newComp = new ArrayList(); + Competitor originalCompetitor = (Competitor) competition.getCompetitors().get( 0 ); + originalCompetitor.setName( "Name2" ); + newComp.add( originalCompetitor ); + newComp.add( new Competitor() ); + // 2) set that new List reference unto the Competition reference + competition.setCompetitors( newComp ); + // 3) attempt the merge + return (Competition) session.merge( competition ); + } + ); + + assertNotSame( competition, competition2 ); + assertNotSame( competition.getCompetitors(), competition2.getCompetitors() ); + assertThat( competition2.getCompetitors().size(), is( 2 ) ); + + scope.inTransaction( + session -> { + Competition c = session.get( Competition.class, competition.getId() ); + assertThat( c.getCompetitors().size(), is( 2 ) ); + session.delete( c ); + } + ); + + cleanup( scope ); + } + + @AfterEach + private void cleanup(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from NumberedNode where parent is not null" ).executeUpdate(); + session.createQuery( "delete from NumberedNode" ).executeUpdate(); + + session.createQuery( "delete from Node where parent is not null" ).executeUpdate(); + session.createQuery( "delete from Node" ).executeUpdate(); + + session.createQuery( "delete from VersionedEntity where parent is not null" ).executeUpdate(); + session.createQuery( "delete from VersionedEntity" ).executeUpdate(); + session.createQuery( "delete from TimestampedEntity" ).executeUpdate(); + + session.createQuery( "delete from Competitor" ).executeUpdate(); + session.createQuery( "delete from Competition" ).executeUpdate(); + + for ( Employer employer : (List) session.createQuery( "from Employer" ).list() ) { + session.delete( employer ); + } + } + ); + + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Node.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.hbm.xml similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Node.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.hbm.xml index 3adc610b8d..dde682a0df 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Node.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Node.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Node.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.java index 3cc9542d33..1f72c655e3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Node.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Node.java @@ -6,7 +6,8 @@ */ //$Id: Node.java 10759 2006-11-08 00:00:53Z steve.ebersole@jboss.com $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; + import java.sql.Date; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/NumberedNode.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/NumberedNode.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/NumberedNode.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/NumberedNode.java index 2ed5b6b70a..a5d5e65ef7 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/NumberedNode.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/NumberedNode.java @@ -6,7 +6,7 @@ */ //$Id: NumberedNode.java 7236 2005-06-20 03:19:34Z oneovthafew $ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.Date; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/OneToOne.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOne.hbm.xml similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/OneToOne.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOne.hbm.xml index bfaf78c3ec..7d9637c782 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/OneToOne.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOne.hbm.xml @@ -17,7 +17,7 @@ Person -> Details is modeled as a bidirectional one to one based on PK. --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/OneToOneMergeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOneMergeTest.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/test/ops/OneToOneMergeTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOneMergeTest.java index 5d8e887309..695b869aec 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/OneToOneMergeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OneToOneMergeTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.io.Serializable; import javax.persistence.CascadeType; @@ -17,54 +17,52 @@ import javax.persistence.JoinColumn; import javax.persistence.MapsId; import javax.persistence.OneToOne; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - import org.hibernate.testing.TestForIssue; -import org.junit.Test; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** - * * @author localEvg */ -@TestForIssue( jiraKey = "HHH-12436" ) -public class OneToOneMergeTest extends BaseEntityManagerFunctionalTestCase { - - @Override - public Class[] getAnnotatedClasses() { - return new Class[]{ - Prima.class, - Secunda.class - }; - } +@TestForIssue(jiraKey = "HHH-12436") +@Jpa( + annotatedClasses = { + OneToOneMergeTest.Prima.class, + OneToOneMergeTest.Secunda.class + } +) +public class OneToOneMergeTest { @Test - public void testMerge() throws Exception { + public void testMerge(EntityManagerFactoryScope scope) throws Exception { - Long primaId = doInJPA( this::entityManagerFactory, entityManager -> { - Prima prima = new Prima(); - prima.setOptionalData(null); + Long primaId = scope.fromTransaction( + entityManager -> { + Prima prima = new Prima(); + prima.setOptionalData( null ); - entityManager.persist(prima); + entityManager.persist( prima ); - return prima.getId(); - } ); + return prima.getId(); + } ); - assertNotNull(primaId); + assertNotNull( primaId ); - doInJPA( this::entityManagerFactory, entityManager -> { - Prima prima = entityManager.find( Prima.class, primaId ); + scope.inTransaction( + entityManager -> { + Prima prima = entityManager.find( Prima.class, primaId ); - Secunda sec = new Secunda(); - sec.setParent(prima); - prima.setOptionalData(sec); + Secunda sec = new Secunda(); + sec.setParent( prima ); + prima.setOptionalData( sec ); - Prima mergedPrima = entityManager.merge(prima); + Prima mergedPrima = entityManager.merge( prima ); - assertNotNull(mergedPrima); - } ); + assertNotNull( mergedPrima ); + } ); } @@ -76,7 +74,7 @@ public class OneToOneMergeTest extends BaseEntityManagerFunctionalTestCase { private Long id; //@PrimaryKeyJoinColumn - @OneToOne(mappedBy = "parent", optional = true , cascade = CascadeType.ALL) + @OneToOne(mappedBy = "parent", optional = true, cascade = CascadeType.ALL) private Secunda optionalData; public Long getId() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/OptLockEntity.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OptLockEntity.hbm.xml similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/ops/OptLockEntity.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/OptLockEntity.hbm.xml index 57ab878b35..a6720b7ab0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/OptLockEntity.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OptLockEntity.hbm.xml @@ -13,7 +13,7 @@ --> - + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OracleNoColumnInsertTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OracleNoColumnInsertTest.java new file mode 100644 index 0000000000..a2c75c90bb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/OracleNoColumnInsertTest.java @@ -0,0 +1,38 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import org.hibernate.dialect.OracleDialect; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialect; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +/** + * @author Vlad Mihalcea + */ +@RequiresDialect(value = OracleDialect.class, version = 900) +@TestForIssue(jiraKey = "HHH-13104") +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/Competition.hbm.xml" +) +@SessionFactory +public class OracleNoColumnInsertTest { + + @Test + public void test(SessionFactoryScope scope) throws Exception { + scope.inTransaction( session -> { + Competition competition = new Competition(); + + session.persist( competition ); + } ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/Person.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Person.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/Person.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/Person.java index bcc6b2e1d6..782f1f6b2a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/Person.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/PersonalDetails.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/PersonalDetails.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/PersonalDetails.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/PersonalDetails.java index 1af858b6a5..af9266d944 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/PersonalDetails.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/PersonalDetails.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/RemoveOrderingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/RemoveOrderingTest.java similarity index 58% rename from hibernate-core/src/test/java/org/hibernate/test/ops/RemoveOrderingTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/RemoveOrderingTest.java index 81a0b4d332..3a43994219 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/RemoveOrderingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/RemoveOrderingTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import javax.persistence.CascadeType; import javax.persistence.Entity; @@ -15,49 +15,43 @@ import javax.persistence.Table; import org.hibernate.Session; -import org.junit.Test; - -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.FailureExpected; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; /** * @author Steve Ebersole */ -public class RemoveOrderingTest extends BaseCoreFunctionalTestCase { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Company.class, Person.class }; - } +@DomainModel( + annotatedClasses = { RemoveOrderingTest.Company.class, RemoveOrderingTest.Person.class } +) +public class RemoveOrderingTest { @Test @TestForIssue( jiraKey = "HHH-8550" ) @FailureExpected( jiraKey = "HHH-8550" ) - public void testManyToOne() throws Exception { - Session session = openSession(); - session.beginTransaction(); - try { - Company company = new Company( 1, "acme" ); - Person person = new Person( 1, "joe", company ); - session.persist( person ); - session.flush(); + public void testManyToOne(SessionFactoryScope scope) throws Exception { + scope.inTransaction( + session -> { + Company company = new Company( 1, "acme" ); + Person person = new Person( 1, "joe", company ); + session.persist( person ); + session.flush(); - company = person.employer; + company = person.employer; - session.delete( company ); - session.delete( person ); - session.flush(); + session.delete( company ); + session.delete( person ); + session.flush(); - session.persist( person ); - session.flush(); + session.persist( person ); + session.flush(); - session.getTransaction().commit(); - } - catch (Exception e) { - session.getTransaction().rollback(); - throw e; - } - session.close(); + session.getTransaction().commit(); + } + ); } @Entity( name="Company" ) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SaveOrUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SaveOrUpdateTest.java new file mode 100755 index 0000000000..f3ab91c6b1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SaveOrUpdateTest.java @@ -0,0 +1,533 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.hibernate.Hibernate; +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.PersistentAttributeInterceptable; + +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.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Gavin King + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/Node.hbm.xml", + concurrencyStrategy = "nonstrict-read-write" +) +@SessionFactory( + generateStatistics = true +) +@ServiceRegistry( + settings = @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "0") +) +public class SaveOrUpdateTest { + + @Test + public void testSaveOrUpdateDeepTree(SessionFactoryScope scope) { + clearCounts( scope ); + + Node root = new Node( "root" ); + Node child = new Node( "child" ); + Node grandchild = new Node( "grandchild" ); + + scope.inTransaction( + session -> { + root.addChild( child ); + child.addChild( grandchild ); + session.saveOrUpdate( root ); + } + ); + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + grandchild.setDescription( "the grand child" ); + Node grandchild2 = new Node( "grandchild2" ); + child.addChild( grandchild2 ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 1, scope ); + clearCounts( scope ); + + Node child2 = new Node( "child2" ); + Node grandchild3 = new Node( "grandchild3" ); + child2.addChild( grandchild3 ); + root.addChild( child2 ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> { + session.delete( grandchild ); + session.delete( grandchild2 ); + session.delete( grandchild3 ); + session.delete( child ); + session.delete( child2 ); + session.delete( root ); + } + ); + } + + @Test + public void testSaveOrUpdateDeepTreeWithGeneratedId(SessionFactoryScope scope) { + boolean instrumented = PersistentAttributeInterceptable.class.isAssignableFrom( NumberedNode.class ); + clearCounts( scope ); + + NumberedNode root = new NumberedNode( "root" ); + NumberedNode c = new NumberedNode( "child" ); + NumberedNode gc = new NumberedNode( "grandchild" ); + scope.inTransaction( + session -> { + root.addChild( c ); + c.addChild( gc ); + session.saveOrUpdate( root ); + } + ); + + assertInsertCount( 3, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + NumberedNode child = (NumberedNode) root.getChildren().iterator().next(); + NumberedNode grandchild = (NumberedNode) child.getChildren().iterator().next(); + grandchild.setDescription( "the grand child" ); + NumberedNode grandchild2 = new NumberedNode( "grandchild2" ); + child.addChild( grandchild2 ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( instrumented ? 1 : 3, scope ); + clearCounts( scope ); + + NumberedNode child2 = new NumberedNode( "child2" ); + NumberedNode grandchild3 = new NumberedNode( "grandchild3" ); + child2.addChild( grandchild3 ); + root.addChild( child2 ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 2, scope ); + assertUpdateCount( instrumented ? 0 : 4, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> { + session.createQuery( "delete from NumberedNode where name like 'grand%'" ).executeUpdate(); + session.createQuery( "delete from NumberedNode where name like 'child%'" ).executeUpdate(); + session.createQuery( "delete from NumberedNode" ).executeUpdate(); + } + ); + } + + @Test + public void testSaveOrUpdateTree(SessionFactoryScope scope) { + clearCounts( scope ); + + Node root = new Node( "root" ); + Node child = new Node( "child" ); + scope.inTransaction( + session -> { + root.addChild( child ); + session.saveOrUpdate( root ); + } + ); + + assertInsertCount( 2, scope ); + clearCounts( scope ); + + root.setDescription( "The root node" ); + child.setDescription( "The child node" ); + + Node secondChild = new Node( "second child" ); + + root.addChild( secondChild ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 2, scope ); + + scope.inTransaction( + session -> { + session.createQuery( "delete from Node where parent is not null" ).executeUpdate(); + session.createQuery( "delete from Node" ).executeUpdate(); + } + ); + } + + @Test + public void testSaveOrUpdateTreeWithGeneratedId(SessionFactoryScope scope) { + clearCounts( scope ); + + NumberedNode root = new NumberedNode( "root" ); + NumberedNode child = new NumberedNode( "child" ); + scope.inTransaction( + session -> { + root.addChild( child ); + session.saveOrUpdate( root ); + } + ); + + assertInsertCount( 2, scope ); + clearCounts( scope ); + + root.setDescription( "The root node" ); + child.setDescription( "The child node" ); + + NumberedNode secondChild = new NumberedNode( "second child" ); + + root.addChild( secondChild ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 2, scope ); + + scope.inTransaction( + session -> { + session.createQuery( "delete from NumberedNode where parent is not null" ).executeUpdate(); + session.createQuery( "delete from NumberedNode" ).executeUpdate(); + } + ); + } + + @Test + public void testSaveOrUpdateManaged(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + NumberedNode root = new NumberedNode( "root" ); + session.saveOrUpdate( root ); + + session.getTransaction().commit(); + + session.beginTransaction(); + NumberedNode child = new NumberedNode( "child" ); + root.addChild( child ); + session.saveOrUpdate( root ); + assertFalse( session.contains( child ) ); + session.flush(); + assertTrue( session.contains( child ) ); + session.getTransaction().commit(); + + assertTrue( root.getChildren().contains( child ) ); + assertThat( root.getChildren().size(), is( 1 ) ); + + session.beginTransaction(); + assertThat( + getRowCount( session, NumberedNode.class ), + is( 2L ) + ); + session.delete( root ); + session.delete( child ); + } + ); + } + + @Test + public void testSaveOrUpdateGot(SessionFactoryScope scope) { + clearCounts( scope ); + + boolean instrumented = PersistentAttributeInterceptable.class.isAssignableFrom( NumberedNode.class ); + + NumberedNode root = new NumberedNode( "root" ); + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( instrumented ? 0 : 1, scope ); + + NumberedNode r = scope.fromTransaction( + session -> { + NumberedNode r1 = session.get( NumberedNode.class, root.getId() ); + Hibernate.initialize( r1.getChildren() ); + return r1; + } + ); + + clearCounts( scope ); + + scope.inTransaction( + session -> { + NumberedNode child = new NumberedNode( "child" ); + r.addChild( child ); + session.saveOrUpdate( r ); + assertTrue( session.contains( child ) ); + session.getTransaction().commit(); + + assertInsertCount( 1, scope ); + assertUpdateCount( instrumented ? 0 : 1, scope ); + + session.beginTransaction(); + assertThat( + getRowCount( session, NumberedNode.class ), + is( 2L ) + ); + session.delete( r ); + session.delete( child ); + } + ); + } + + @Test + public void testSaveOrUpdateGotWithMutableProp(SessionFactoryScope scope) { + clearCounts( scope ); + + Node root = new Node( "root" ); + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + + Node root1 = scope.fromTransaction( + session -> { + Node r1 = session.get( Node.class, "root" ); + Hibernate.initialize( r1.getChildren() ); + return r1; + } + ); + + clearCounts( scope ); + + scope.inTransaction( + session -> { + Node child = new Node( "child" ); + root1.addChild( child ); + session.saveOrUpdate( root1 ); + assertTrue( session.contains( child ) ); + session.getTransaction().commit(); + + assertInsertCount( 1, scope ); + assertUpdateCount( 1, scope ); //note: will fail here if no second-level cache + + session.beginTransaction(); + assertThat( + getRowCount( session, Node.class ), + is( 2L ) + ); + session.delete( root1 ); + session.delete( child ); + } + ); + } + + @Test + public void testEvictThenSaveOrUpdate(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Node parent = new Node( "1:parent" ); + Node child = new Node( "2:child" ); + Node grandchild = new Node( "3:grandchild" ); + parent.addChild( child ); + child.addChild( grandchild ); + session.saveOrUpdate( parent ); + } + ); + + + Session s1 = scope.getSessionFactory().openSession(); + Session s2 = null; + try { + s1.getTransaction().begin(); + Node child = s1.load( Node.class, "2:child" ); + assertTrue( s1.contains( child ) ); + assertFalse( Hibernate.isInitialized( child ) ); + assertTrue( s1.contains( child.getParent() ) ); + assertTrue( Hibernate.isInitialized( child ) ); + assertFalse( Hibernate.isInitialized( child.getChildren() ) ); + assertFalse( Hibernate.isInitialized( child.getParent() ) ); + assertTrue( s1.contains( child ) ); + s1.evict( child ); + assertFalse( s1.contains( child ) ); + assertTrue( s1.contains( child.getParent() ) ); + + s2 = scope.getSessionFactory().openSession(); + try { + s2.getTransaction().begin(); + s2.saveOrUpdate( child ); + fail(); + } + catch (HibernateException ex) { + // expected because parent is connected to s1 + } + finally { + s2.getTransaction().rollback(); + } + s2.close(); + + s1.evict( child.getParent() ); + assertFalse( s1.contains( child.getParent() ) ); + + s2 = scope.getSessionFactory().openSession(); + s2.getTransaction().begin(); + s2.saveOrUpdate( child ); + assertTrue( s2.contains( child ) ); + assertFalse( s1.contains( child ) ); + assertTrue( s2.contains( child.getParent() ) ); + assertFalse( s1.contains( child.getParent() ) ); + assertFalse( Hibernate.isInitialized( child.getChildren() ) ); + assertFalse( Hibernate.isInitialized( child.getParent() ) ); + assertThat( child.getChildren().size(), is( 1 ) ); + assertThat( child.getParent().getName(), is( "1:parent" ) ); + assertTrue( Hibernate.isInitialized( child.getChildren() ) ); + assertFalse( Hibernate.isInitialized( child.getParent() ) ); + assertNull( child.getParent().getDescription() ); + assertTrue( Hibernate.isInitialized( child.getParent() ) ); + + s1.getTransaction().commit(); + s2.getTransaction().commit(); + } + finally { + if ( s1.getTransaction().isActive() ) { + s1.getTransaction().rollback(); + } + s1.close(); + if ( s2 != null ) { + if ( s2.getTransaction().isActive() ) { + s1.getTransaction().rollback(); + } + s2.close(); + } + } + + scope.inTransaction( + session -> { + session.delete( session.get( Node.class, "3:grandchild" ) ); + session.delete( session.get( Node.class, "2:child" ) ); + session.delete( session.get( Node.class, "1:parent" ) ); + } + ); + } + + @Test + public void testSavePersistentEntityWithUpdate(SessionFactoryScope scope) { + clearCounts( scope ); + + NumberedNode root = new NumberedNode( "root" ); + root.setName( "a name" ); + scope.inTransaction( + session -> + session.saveOrUpdate( root ) + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 0, scope ); + clearCounts( scope ); + + NumberedNode r = scope.fromTransaction( + session -> { + NumberedNode node = session.get( NumberedNode.class, root.getId() ); + assertThat( node.getName(), is( "a name" ) ); + node.setName( "a new name" ); + session.save( node ); + return node; + } + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 1, scope ); + clearCounts( scope ); + + scope.inTransaction( + session -> { + NumberedNode node = session.get( NumberedNode.class, r.getId() ); + assertThat( node.getName(), is( "a new name" ) ); + session.delete( node ); + } + ); + } + + private Long getRowCount(Session s, Class clazz) { + CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); + CriteriaQuery criteria = criteriaBuilder.createQuery( Long.class ); + Root root = criteria.from( clazz ); + criteria.select( criteriaBuilder.count( root ) ); + return s.createQuery( criteria ).uniqueResult(); + } + + private void clearCounts(SessionFactoryScope scope) { + scope.getSessionFactory().getStatistics().clear(); + } + + private void assertInsertCount(int count, SessionFactoryScope scope) { + int inserts = (int) scope.getSessionFactory().getStatistics().getEntityInsertCount(); + assertThat( inserts, is( count ) ); + } + + private void assertUpdateCount(int count, SessionFactoryScope scope) { + int updates = (int) scope.getSessionFactory().getStatistics().getEntityUpdateCount(); + assertThat( updates, is( count ) ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.hbm.xml similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.hbm.xml index a9e7e542ab..764ce636a8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.hbm.xml @@ -10,7 +10,7 @@ "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.java index 4a4eda4a92..56d682e4d6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleEntity.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** * @author Steve Ebersole diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleOpsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleOpsTest.java new file mode 100755 index 0000000000..6b0814ab0d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SimpleOpsTest.java @@ -0,0 +1,110 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.ops; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Gail Badner + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/ops/SimpleEntity.hbm.xml" +) +public class SimpleOpsTest extends AbstractOperationTestCase { + + public String[] getMappings() { + return new String[] {}; + } + + @Test + public void testBasicOperations(SessionFactoryScope scope) { + clearCounts( scope ); + + Long id = 1L; + scope.inTransaction( + session -> { + SimpleEntity entity = new SimpleEntity(); + entity.setId( id ); + entity.setName( "name" ); + session.save( entity ); + } + ); + + assertInsertCount( 1, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 0, scope ); + + clearCounts( scope ); + + scope.inTransaction( + session -> { + SimpleEntity entity = session.get( SimpleEntity.class, id ); + assertThat( entity.getId(), is( 1L ) ); + assertThat( entity.getName(), is( "name" ) ); + entity.setName( "new name" ); + } + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 1, scope ); + assertDeleteCount( 0, scope ); + + clearCounts( scope ); + + SimpleEntity simpleEntity = scope.fromTransaction( + session -> { + SimpleEntity entity = session.load( SimpleEntity.class, id ); + assertFalse( Hibernate.isInitialized( entity ) ); + assertThat( entity.getId(), is( 1L ) ); + assertThat( entity.getName(), is( "new name" ) ); + assertTrue( Hibernate.isInitialized( entity ) ); + return entity; + } + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 0, scope ); + + simpleEntity.setName( "another new name" ); + + scope.inTransaction( + session -> + session.merge( simpleEntity ) + ); + + + assertInsertCount( 0, scope ); + assertUpdateCount( 1, scope ); + assertDeleteCount( 0, scope ); + + clearCounts( scope ); + + scope.inTransaction( + session -> { + SimpleEntity entity = session.get( SimpleEntity.class, id ); + assertThat( entity.getId(), is( 1L ) ); + assertThat( entity.getName(), is( "another new name" ) ); + session.delete( entity ); + } + ); + + assertInsertCount( 0, scope ); + assertUpdateCount( 0, scope ); + assertDeleteCount( 1, scope ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SubCategory.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubCategory.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/SubCategory.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubCategory.java index 7574d0d380..5b39f1bdfa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SubCategory.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubCategory.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** * @author Gail Badner diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SubItem.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubItem.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/SubItem.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubItem.java index 6dbe8bce3e..fc849f65a7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SubItem.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/SubItem.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; /** * @author Gail Badner diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/TimestampedEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/TimestampedEntity.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/ops/TimestampedEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/TimestampedEntity.java index cbe45db921..24ea1805ca 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/TimestampedEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/TimestampedEntity.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.Date; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/VersionedEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/VersionedEntity.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/ops/VersionedEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/ops/VersionedEntity.java index 570b3837e4..33978552bb 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/VersionedEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/VersionedEntity.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.ops; +package org.hibernate.orm.test.ops; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/BasicGetLoadAccessTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/BasicGetLoadAccessTest.java index 1813a62217..42b941f8de 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/BasicGetLoadAccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/BasicGetLoadAccessTest.java @@ -15,30 +15,144 @@ import javax.persistence.Table; import org.hibernate.LockMode; import org.hibernate.LockOptions; -import org.hibernate.Session; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.boot.MetadataSources; -import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; /** * @author Steve Ebersole */ -public class BasicGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCase { - @Override - protected void applyMetadataSources(MetadataSources sources) { - super.applyMetadataSources( sources ); - sources.addAnnotatedClass( User.class ); +@DomainModel( + annotatedClasses = BasicGetLoadAccessTest.User.class +) +@SessionFactory +public class BasicGetLoadAccessTest { + + @AfterEach + public void tearDown(SessionFactoryScope scope){ + scope.inTransaction( + session -> + session.createQuery( "delete from User" ).executeUpdate() + ); } - @Entity( name = "User" ) - @Table( name = "my_user" ) + @Test + public void testIt(SessionFactoryScope scope) { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // create a row + scope.inTransaction( + session -> + session.save( new User( "steve" ) ) + ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // test `get` access + scope.inTransaction( + session -> + session.get( User.class, 1 ) + ); + + + scope.inTransaction( + session -> + session.get( User.class, 1, LockMode.PESSIMISTIC_WRITE ) + ); + + scope.inTransaction( + session -> + session.get( User.class, 1, LockOptions.UPGRADE ) + ); + + scope.inTransaction( + session -> + session.byId( User.class ).load( 1 ) + ); + + scope.inTransaction( + session -> + session.byId( User.class ).with( LockOptions.UPGRADE ).load( 1 ) + ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // test `load` access + scope.inTransaction( + session -> + session.load( User.class, 1 ) + ); + + scope.inTransaction( + session -> + session.load( User.class, 1, LockMode.PESSIMISTIC_WRITE ) + ); + + scope.inTransaction( + session -> + session.load( User.class, 1, LockOptions.UPGRADE ) + ); + + scope.inTransaction( + session -> + session.byId( User.class ).getReference( 1 ) + ); + + scope.inTransaction( + session -> + session.byId( User.class ).with( LockOptions.UPGRADE ).getReference( 1 ) + ); + } + + @Test + public void testNullLoadResult(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + assertNull( session.byId( User.class ).load( -1 ) ); + + Optional user = session.byId( User.class ).loadOptional( -1 ); + assertNotNull( user ); + assertFalse( user.isPresent() ); + try { + user.get(); + fail( "Expecting call to Optional#get to throw NoSuchElementException" ); + } + catch (NoSuchElementException expected) { + // the expected result... + } + } + ); + } + + @Test + public void testNullQueryResult(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + assertNull( session.createQuery( "select u from User u where u.id = -1" ).uniqueResult() ); + + Optional user = session.createQuery( "select u from User u where u.id = -1" ).uniqueResultOptional(); + assertNotNull( user ); + assertFalse( user.isPresent() ); + try { + user.get(); + fail( "Expecting call to Optional#get to throw NoSuchElementException" ); + } + catch (NoSuchElementException expected) { + // the expected result... + } + } + ); + } + + @Entity(name = "User") + @Table(name = "my_user") public static class User { private Integer id; private String name; @@ -51,8 +165,8 @@ public class BasicGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCase } @Id - @GeneratedValue( generator = "increment" ) - @GenericGenerator( name = "increment", strategy = "increment" ) + @GeneratedValue(generator = "increment") + @GenericGenerator(name = "increment", strategy = "increment") public Integer getId() { return id; } @@ -70,125 +184,4 @@ public class BasicGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCase } } - @Test - public void testIt() { - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // create a row - Session s = openSession(); - s.beginTransaction(); - s.save( new User( "steve" ) ); - s.getTransaction().commit(); - s.close(); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // test `get` access - s = openSession(); - s.beginTransaction(); - User user = s.get( User.class, 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.get( User.class, 1, LockMode.PESSIMISTIC_WRITE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.get( User.class, 1, LockOptions.UPGRADE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( User.class ).load( 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( User.class ).with( LockOptions.UPGRADE ).load( 1 ); - s.getTransaction().commit(); - s.close(); - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // test `load` access - s = openSession(); - s.beginTransaction(); - user = s.load( User.class, 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.load( User.class, 1, LockMode.PESSIMISTIC_WRITE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.load( User.class, 1, LockOptions.UPGRADE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( User.class ).getReference( 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( User.class ).with( LockOptions.UPGRADE ).getReference( 1 ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testNullLoadResult() { - Session s = openSession(); - s.beginTransaction(); - - assertNull( s.byId( User.class ).load( -1 ) ); - - Optional user = s.byId( User.class ).loadOptional( -1 ); - assertNotNull( user ); - assertFalse( user.isPresent() ); - try { - user.get(); - fail( "Expecting call to Optional#get to throw NoSuchElementException" ); - } - catch (NoSuchElementException expected) { - // the expected result... - } - - s.getTransaction().commit(); - s.close(); - - } - - @Test - public void testNullQueryResult() { - Session s = openSession(); - s.beginTransaction(); - - assertNull( s.createQuery( "select u from User u where u.id = -1" ).uniqueResult() ); - - Optional user = s.createQuery( "select u from User u where u.id = -1" ).uniqueResultOptional(); - assertNotNull( user ); - assertFalse( user.isPresent() ); - try { - user.get(); - fail( "Expecting call to Optional#get to throw NoSuchElementException" ); - } - catch (NoSuchElementException expected) { - // the expected result... - } - - s.getTransaction().commit(); - s.close(); - - } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/ProxiedGetLoadAccessTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/ProxiedGetLoadAccessTest.java index 805c8d89a0..315c5a9c69 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/ProxiedGetLoadAccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/ops/genericApi/ProxiedGetLoadAccessTest.java @@ -13,33 +13,118 @@ import javax.persistence.Table; import org.hibernate.LockMode; import org.hibernate.LockOptions; -import org.hibernate.Session; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Proxy; -import org.hibernate.boot.MetadataSources; -import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; /** * @author Steve Ebersole */ -public class ProxiedGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCase { - @Override - protected void applyMetadataSources(MetadataSources sources) { - super.applyMetadataSources( sources ); - sources.addAnnotatedClass( UserImpl.class ); +@DomainModel( + annotatedClasses = ProxiedGetLoadAccessTest.UserImpl.class +) +@SessionFactory +public class ProxiedGetLoadAccessTest { + + @Test + public void testIt(SessionFactoryScope scope) { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // create a row + scope.inTransaction( + session -> + session.save( new UserImpl( "steve" ) ) + ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // test `get` access + scope.inTransaction( + session -> { + // THis technically works + session.get( UserImpl.class, 1 ); + session.get( User.class, 1 ); + } + ); + + scope.inTransaction( + session -> { + session.get( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE ); + session.get( User.class, 1, LockMode.PESSIMISTIC_WRITE ); + } + ); + + scope.inTransaction( + session -> { + session.get( UserImpl.class, 1, LockOptions.UPGRADE ); + session.get( User.class, 1, LockOptions.UPGRADE ); + } + ); + + scope.inTransaction( + session -> { + session.byId( UserImpl.class ).load( 1 ); + session.byId( User.class ).load( 1 ); + } + ); + + scope.inTransaction( + session -> { + session.byId( UserImpl.class ).with( LockOptions.UPGRADE ).load( 1 ); + session.byId( User.class ).with( LockOptions.UPGRADE ).load( 1 ); + } + ); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // test `load` access + scope.inTransaction( + session -> { + session.load( UserImpl.class, 1 ); + session.load( User.class, 1 ); + } + ); + + scope.inTransaction( + session -> { + session.load( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE ); + session.load( User.class, 1, LockMode.PESSIMISTIC_WRITE ); + } + ); + scope.inTransaction( + session -> { + session.load( UserImpl.class, 1, LockOptions.UPGRADE ); + session.load( User.class, 1, LockOptions.UPGRADE ); + } + ); + + scope.inTransaction( + session -> { + session.byId( UserImpl.class ).getReference( 1 ); + session.byId( User.class ).getReference( 1 ); + } + ); + + scope.inTransaction( + session -> { + session.byId( UserImpl.class ).with( LockOptions.UPGRADE ).getReference( 1 ); + session.byId( User.class ).with( LockOptions.UPGRADE ).getReference( 1 ); + } + ); } - public static interface User { - public Integer getId(); - public String getName(); - public void setName(String name); + public interface User { + Integer getId(); + + String getName(); + + void setName(String name); } - @Entity( name = "User" ) - @Table( name = "my_user" ) - @Proxy( proxyClass = User.class ) + @Entity(name = "User") + @Table(name = "my_user") + @Proxy(proxyClass = User.class) public static class UserImpl implements User { private Integer id; private String name; @@ -52,8 +137,8 @@ public class ProxiedGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCas } @Id - @GeneratedValue( generator = "increment" ) - @GenericGenerator( name = "increment", strategy = "increment" ) + @GeneratedValue(generator = "increment") + @GenericGenerator(name = "increment", strategy = "increment") @Override public Integer getId() { return id; @@ -73,91 +158,4 @@ public class ProxiedGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCas this.name = name; } } - - @Test - public void testIt() { - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // create a row - Session s = openSession(); - s.beginTransaction(); - s.save( new UserImpl( "steve" ) ); - s.getTransaction().commit(); - s.close(); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // test `get` access - s = openSession(); - s.beginTransaction(); - // THis technically works - User user = s.get( UserImpl.class, 1 ); - user = s.get( User.class, 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.get( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE ); - user = s.get( User.class, 1, LockMode.PESSIMISTIC_WRITE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.get( UserImpl.class, 1, LockOptions.UPGRADE ); - user = s.get( User.class, 1, LockOptions.UPGRADE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( UserImpl.class ).load( 1 ); - user = s.byId( User.class ).load( 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( UserImpl.class ).with( LockOptions.UPGRADE ).load( 1 ); - user = s.byId( User.class ).with( LockOptions.UPGRADE ).load( 1 ); - s.getTransaction().commit(); - s.close(); - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // test `load` access - s = openSession(); - s.beginTransaction(); - user = s.load( UserImpl.class, 1 ); - user = s.load( User.class, 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.load( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE ); - user = s.load( User.class, 1, LockMode.PESSIMISTIC_WRITE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.load( UserImpl.class, 1, LockOptions.UPGRADE ); - user = s.load( User.class, 1, LockOptions.UPGRADE ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( UserImpl.class ).getReference( 1 ); - user = s.byId( User.class ).getReference( 1 ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = s.byId( UserImpl.class ).with( LockOptions.UPGRADE ).getReference( 1 ); - user = s.byId( User.class ).with( LockOptions.UPGRADE ).getReference( 1 ); - s.getTransaction().commit(); - s.close(); - } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Address.java b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Address.java similarity index 90% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Address.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Address.java index 3039c9fced..f562a58168 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Address.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Address.java @@ -6,7 +6,7 @@ */ //$Id: Address.java 7192 2005-06-18 14:40:15Z oneovthafew $ -package org.hibernate.test.unionsubclass2; +package org.hibernate.orm.test.unionsubclass2; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Customer.java b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Customer.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Customer.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Customer.java index 4635a430d1..948aab4a66 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Customer.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Customer.java @@ -6,7 +6,7 @@ */ //$Id: Customer.java 7192 2005-06-18 14:40:15Z oneovthafew $ -package org.hibernate.test.unionsubclass2; +package org.hibernate.orm.test.unionsubclass2; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Employee.java b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Employee.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Employee.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Employee.java index 4fab07b13f..92328849c5 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Employee.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Employee.java @@ -6,7 +6,7 @@ */ //$Id: Employee.java 7192 2005-06-18 14:40:15Z oneovthafew $ -package org.hibernate.test.unionsubclass2; +package org.hibernate.orm.test.unionsubclass2; import java.math.BigDecimal; /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.hbm.xml similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.hbm.xml index ce6c63f720..a29fc94967 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.hbm.xml @@ -22,7 +22,7 @@ --> diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.java b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.java similarity index 97% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.java index 8cceaa8e31..9f25233120 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/Person.java @@ -6,7 +6,7 @@ */ //$Id: Person.java 7192 2005-06-18 14:40:15Z oneovthafew $ -package org.hibernate.test.unionsubclass2; +package org.hibernate.orm.test.unionsubclass2; diff --git a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/UnionSubclassTest.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/UnionSubclassTest.java index f875784121..3bcafd4d3f 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/unionsubclass2/UnionSubclassTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.unionsubclass2; +package org.hibernate.orm.test.unionsubclass2; import java.math.BigDecimal; import java.util.List; @@ -13,28 +13,35 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.hibernate.Hibernate; -import org.hibernate.dialect.HSQLDialect; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author Gavin King */ -public class UnionSubclassTest extends BaseCoreFunctionalTestCase { +@DomainModel( + xmlMappings = "org/hibernate/orm/test/unionsubclass2/Person.hbm.xml" +) +@SessionFactory +public class UnionSubclassTest { protected String[] getMappings() { - return new String[] { "unionsubclass2/Person.hbm.xml" }; + return new String[] {}; } @Test - public void testUnionSubclass() { - - inTransaction( + public void testUnionSubclass(SessionFactoryScope scope) { + scope.inTransaction( s -> { Employee mark = new Employee(); mark.setName( "Mark" ); @@ -61,7 +68,13 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase { s.save( mark ); s.save( joe ); - assertEquals( s.createQuery( "from java.io.Serializable" ).list().size(), 0 ); + try { + assertEquals( s.createQuery( "from java.io.Serializable" ).list().size(), 0 ); + fail( "IllegalArgumentException expected" ); + } + catch (Exception e) { + assertThat( e, instanceOf( IllegalArgumentException.class ) ); + } assertEquals( s.createQuery( "from Person" ).list().size(), 3 ); assertEquals( s.createQuery( "from Person p where p.class = Customer" ).list().size(), 1 ); @@ -109,7 +122,8 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase { Root root = criteria.from( Person.class ); CriteriaBuilder.In addresses = criteriaBuilder.in( root.get( "address" ) ); - addresses.value( new Address[] { mark.getAddress(), joe.getAddress() } ); + addresses.value( mark.getAddress() ); + addresses.value( joe.getAddress() ); criteria.where( addresses ); s.createQuery( criteria ).list(); @@ -126,12 +140,8 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase { } @Test - public void testQuerySubclassAttribute() { - if ( getDialect() instanceof HSQLDialect ) { - return; // TODO : why?? - } - - inTransaction( + public void testQuerySubclassAttribute(SessionFactoryScope scope) { + scope.inTransaction( s -> { Person p = new Person(); p.setName( "Emmanuel" ); @@ -175,8 +185,8 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase { } @Test - public void testCustomColumnReadAndWrite() { - inTransaction( + public void testCustomColumnReadAndWrite(SessionFactoryScope scope) { + scope.inTransaction( s -> { final double HEIGHT_INCHES = 73; final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d; @@ -240,7 +250,7 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase { employeeCriteria.where( criteriaBuilder.between( employeeRoot.get( "passwordExpiryDays" ), PASSWORD_EXPIRY_DAYS - 0.01d, - PASSWORD_EXPIRY_DAYS - 0.01d + PASSWORD_EXPIRY_DAYS + 0.01d ) ); e = s.createQuery( employeeCriteria ).uniqueResult(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyCollectionConsistencyTest.java b/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyCollectionConsistencyTest.java index 4d992f32e5..0a95285028 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyCollectionConsistencyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyCollectionConsistencyTest.java @@ -7,124 +7,134 @@ package org.hibernate.test.extralazy; import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Vlad Mihalcea */ -public class ExtraLazyCollectionConsistencyTest extends BaseCoreFunctionalTestCase { +@DomainModel( + xmlMappings = { + "org/hibernate/test/extralazy/UserGroup.hbm.xml" + } +) +@SessionFactory +public class ExtraLazyCollectionConsistencyTest { private User user; - @Override - public String[] getMappings() { - return new String[] { "extralazy/UserGroup.hbm.xml","extralazy/Parent.hbm.xml","extralazy/Child.hbm.xml" }; + @BeforeEach + protected void prepareTest(SessionFactoryScope scope) { + scope.inTransaction( session -> { + user = new User( "victor", "hugo" ); + session.persist( user ); + } ); } - @Override - protected void prepareTest() { - doInHibernate( this::sessionFactory, session -> { - user = new User("victor", "hugo"); - session.persist(user); - }); - } - - @Override - protected boolean isCleanupTestDataRequired() { - return true; + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from Document" ).executeUpdate(); + session.createQuery( "delete from User" ).executeUpdate(); + } + ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetSize() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); - Document document = new Document("Les Miserables", "sad", _user); - assertEquals(1, _user.getDocuments().size()); - }); + public void testSetSize(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); + new Document( "Les Miserables", "sad", _user ); + assertThat( _user.getDocuments().size(), is( 1 ) ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetIterator() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); - Document document = new Document("Les Miserables", "sad", _user); - assertTrue(_user.getDocuments().iterator().hasNext()); - }); + public void testSetIterator(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); + new Document( "Les Miserables", "sad", _user ); + assertTrue( _user.getDocuments().iterator().hasNext() ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetIsEmpty() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); - Document document = new Document("Les Miserables", "sad", _user); - assertFalse(_user.getDocuments().isEmpty()); - }); + public void testSetIsEmpty(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); + new Document( "Les Miserables", "sad", _user ); + assertFalse( _user.getDocuments().isEmpty() ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetContains() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); - Document document = new Document("Les Miserables", "sad", _user); - assertTrue(_user.getDocuments().contains(document)); - }); + public void testSetContains(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); + Document document = new Document( "Les Miserables", "sad", _user ); + assertTrue( _user.getDocuments().contains( document ) ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetAdd() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); + public void testSetAdd(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); Document document = new Document(); - document.setTitle("Les Miserables"); - document.setContent("sad"); - document.setOwner(_user); - assertTrue("not added", _user.getDocuments().add(document)); - assertFalse("added", _user.getDocuments().add(document)); - }); + document.setTitle( "Les Miserables" ); + document.setContent( "sad" ); + document.setOwner( _user ); + assertTrue( _user.getDocuments().add( document ), "not added" ); + assertFalse( _user.getDocuments().add( document ), "added" ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetRemove() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); + public void testSetRemove(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); - Document document = new Document("Les Miserables", "sad", _user); - assertTrue("not removed", _user.getDocuments().remove(document)); - }); + Document document = new Document( "Les Miserables", "sad", _user ); + assertTrue( _user.getDocuments().remove( document ), "not removed" ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetToArray() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); + public void testSetToArray(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); - Document document = new Document("Les Miserables", "sad", _user); - assertEquals(1, _user.getDocuments().toArray().length); - }); + new Document( "Les Miserables", "sad", _user ); + assertThat( _user.getDocuments().toArray().length, is( 1 ) ); + } ); } @Test @TestForIssue(jiraKey = "HHH-9933") - public void testSetToArrayTyped() { - doInHibernate( this::sessionFactory, session -> { - User _user = session.get(User.class, user.getName()); + public void testSetToArrayTyped(SessionFactoryScope scope) { + scope.inTransaction( session -> { + User _user = session.get( User.class, user.getName() ); - Document document = new Document("Les Miserables", "sad", _user); - assertEquals(1, _user.getDocuments().toArray(new Document[0]).length); - }); + new Document( "Les Miserables", "sad", _user ); + assertThat( _user.getDocuments().size(), is( 1 ) ); + } ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyTest.java b/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyTest.java index 0780002091..50935fa2d0 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/extralazy/ExtraLazyTest.java @@ -10,336 +10,352 @@ import java.util.List; import java.util.Map; import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.FailureExpected; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Gavin King */ -public class ExtraLazyTest extends BaseCoreFunctionalTestCase { - @Override - public String[] getMappings() { - return new String[] { "extralazy/UserGroup.hbm.xml","extralazy/Parent.hbm.xml","extralazy/Child.hbm.xml" }; - } +@DomainModel( + annotatedClasses = { School.class, Student.class, Championship.class }, + xmlMappings = + { + "org/hibernate/test/extralazy/UserGroup.hbm.xml", + "org/hibernate/test/extralazy/Parent.hbm.xml", + "org/hibernate/test/extralazy/Child.hbm.xml" + } +) +@SessionFactory +public class ExtraLazyTest { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { School.class, Student.class, Championship.class }; + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from Group" ).executeUpdate(); + session.createQuery( "delete from Document" ).executeUpdate(); + session.createQuery( "delete from User" ).executeUpdate(); + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from Parent" ).executeUpdate(); + session.createQuery( "delete from Student" ).executeUpdate(); + session.createQuery( "delete from School" ).executeUpdate(); + session.createQuery( "delete from Championship" ).executeUpdate(); + } + ); } @Test - public void testOrphanDelete() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - User gavin = new User("gavin", "secret"); - Document hia = new Document("HiA", "blah blah blah", gavin); - Document hia2 = new Document("HiA2", "blah blah blah blah", gavin); - s.persist(gavin); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - gavin = (User) s.get(User.class, "gavin"); - assertEquals( 2, gavin.getDocuments().size() ); - gavin.getDocuments().remove(hia2); - assertFalse( gavin.getDocuments().contains(hia2) ); - assertTrue( gavin.getDocuments().contains(hia) ); - assertEquals( 1, gavin.getDocuments().size() ); - assertFalse( Hibernate.isInitialized( gavin.getDocuments() ) ); - t.commit(); - s.close(); + public void testOrphanDelete(SessionFactoryScope scope) { + User user = new User( "gavin", "secret" ); + Document hia = new Document( "HiA", "blah blah blah", user ); + Document hia2 = new Document( "HiA2", "blah blah blah blah", user ); + scope.inTransaction( + session -> + session.persist( user ) + ); - s = openSession(); - t = s.beginTransaction(); - gavin = (User) s.get(User.class, "gavin"); - assertEquals( 1, gavin.getDocuments().size() ); - assertFalse( gavin.getDocuments().contains(hia2) ); - assertTrue( gavin.getDocuments().contains(hia) ); - assertFalse( Hibernate.isInitialized( gavin.getDocuments() ) ); - assertNull( s.get(Document.class, "HiA2") ); - gavin.getDocuments().clear(); - assertTrue( Hibernate.isInitialized( gavin.getDocuments() ) ); - s.delete(gavin); - t.commit(); - s.close(); - } - - @Test - public void testGet() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - User gavin = new User("gavin", "secret"); - User turin = new User("turin", "tiger"); - Group g = new Group("developers"); - g.getUsers().put("gavin", gavin); - g.getUsers().put("turin", turin); - s.persist(g); - gavin.getSession().put( "foo", new SessionAttribute("foo", "foo bar baz") ); - gavin.getSession().put( "bar", new SessionAttribute("bar", "foo bar baz 2") ); - t.commit(); - s.close(); + scope.inTransaction( + session -> { + User gavin = session.get( User.class, "gavin" ); + assertThat( gavin.getDocuments().size(), is( 2 ) ); + gavin.getDocuments().remove( hia2 ); + assertFalse( gavin.getDocuments().contains( hia2 ) ); + assertTrue( gavin.getDocuments().contains( hia ) ); + assertThat( gavin.getDocuments().size(), is( 1 ) ); + assertFalse( Hibernate.isInitialized( gavin.getDocuments() ) ); + } + ); - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - gavin = (User) g.getUsers().get("gavin"); - turin = (User) g.getUsers().get("turin"); - assertNotNull(gavin); - assertNotNull(turin); - assertNull( g.getUsers().get("emmanuel") ); - assertFalse( Hibernate.isInitialized( g.getUsers() ) ); - assertNotNull( gavin.getSession().get("foo") ); - assertNull( turin.getSession().get("foo") ); - assertFalse( Hibernate.isInitialized( gavin.getSession() ) ); - assertFalse( Hibernate.isInitialized( turin.getSession() ) ); - s.delete(gavin); - s.delete(turin); - s.delete(g); - t.commit(); - s.close(); - } - - @Test - public void testRemoveClear() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - User gavin = new User("gavin", "secret"); - User turin = new User("turin", "tiger"); - Group g = new Group("developers"); - g.getUsers().put("gavin", gavin); - g.getUsers().put("turin", turin); - s.persist(g); - gavin.getSession().put( "foo", new SessionAttribute("foo", "foo bar baz") ); - gavin.getSession().put( "bar", new SessionAttribute("bar", "foo bar baz 2") ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - gavin = (User) g.getUsers().get("gavin"); - turin = (User) g.getUsers().get("turin"); - assertFalse( Hibernate.isInitialized( g.getUsers() ) ); - g.getUsers().clear(); - gavin.getSession().remove("foo"); - assertTrue( Hibernate.isInitialized( g.getUsers() ) ); - assertTrue( Hibernate.isInitialized( gavin.getSession() ) ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - assertTrue( g.getUsers().isEmpty() ); - assertFalse( Hibernate.isInitialized( g.getUsers() ) ); - gavin = (User) s.get(User.class, "gavin"); - assertFalse( gavin.getSession().containsKey("foo") ); - assertFalse( Hibernate.isInitialized( gavin.getSession() ) ); - s.delete(gavin); - s.delete(turin); - s.delete(g); - t.commit(); - s.close(); - } - - @Test - public void testIndexFormulaMap() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - User gavin = new User("gavin", "secret"); - User turin = new User("turin", "tiger"); - Group g = new Group("developers"); - g.getUsers().put("gavin", gavin); - g.getUsers().put("turin", turin); - s.persist(g); - gavin.getSession().put( "foo", new SessionAttribute("foo", "foo bar baz") ); - gavin.getSession().put( "bar", new SessionAttribute("bar", "foo bar baz 2") ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - assertEquals( g.getUsers().size(), 2 ); - g.getUsers().remove("turin"); - Map smap = ( (User) g.getUsers().get("gavin") ).getSession(); - assertEquals(smap.size(), 2); - smap.remove("bar"); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - assertEquals( g.getUsers().size(), 1 ); - smap = ( (User) g.getUsers().get("gavin") ).getSession(); - assertEquals(smap.size(), 1); - gavin = (User) g.getUsers().put("gavin", turin); - s.delete(gavin); - assertEquals( s.createQuery("select count(*) from SessionAttribute").uniqueResult(), new Long(0) ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - g = (Group) s.get(Group.class, "developers"); - assertEquals( g.getUsers().size(), 1 ); - turin = (User) g.getUsers().get("turin"); - smap = turin.getSession(); - assertEquals(smap.size(), 0); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(1) ); - s.delete(g); - s.delete(turin); - assertEquals( s.createQuery("select count(*) from User").uniqueResult(), new Long(0) ); - t.commit(); - s.close(); - } - - @Test - @RequiresDialectFeature( DialectChecks.DoubleQuoteQuoting.class ) - public void testSQLQuery() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - User gavin = new User("gavin", "secret"); - User turin = new User("turin", "tiger"); - gavin.getSession().put( "foo", new SessionAttribute("foo", "foo bar baz") ); - gavin.getSession().put( "bar", new SessionAttribute("bar", "foo bar baz 2") ); - s.persist(gavin); - s.persist(turin); - s.flush(); - s.clear(); - List results = s.getNamedQuery("userSessionData").setParameter("uname", "%in").list(); - assertEquals( results.size(), 2 ); - gavin = (User) ( (Object[]) results.get(0) )[0]; - assertEquals( gavin.getName(), "gavin" ); - assertEquals( gavin.getSession().size(), 2 ); - s.createQuery("delete SessionAttribute").executeUpdate(); - s.createQuery("delete User").executeUpdate(); - t.commit(); - s.close(); - + scope.inTransaction( + session -> { + User gavin = session.get( User.class, "gavin" ); + assertThat( gavin.getDocuments().size(), is( 1 ) ); + assertFalse( gavin.getDocuments().contains( hia2 ) ); + assertTrue( gavin.getDocuments().contains( hia ) ); + assertFalse( Hibernate.isInitialized( gavin.getDocuments() ) ); + assertNull( session.get( Document.class, "HiA2" ) ); + gavin.getDocuments().clear(); + assertTrue( Hibernate.isInitialized( gavin.getDocuments() ) ); + session.delete( gavin ); + } + ); } @Test - @TestForIssue(jiraKey="HHH-4294") - public void testMap() { - Session session1 = openSession(); - Transaction tx1 = session1.beginTransaction(); - Parent parent = new Parent (); - Child child = new Child (); - child.setFirstName("Ben"); - parent.getChildren().put(child.getFirstName(), child); - child.setParent(parent); - session1.save(parent); - tx1.commit(); - session1.close(); + public void testGet(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + User gavin = new User( "gavin", "secret" ); + User turin = new User( "turin", "tiger" ); + Group g = new Group( "developers" ); + g.getUsers().put( "gavin", gavin ); + g.getUsers().put( "turin", turin ); + session.persist( g ); + gavin.getSession().put( "foo", new SessionAttribute( "foo", "foo bar baz" ) ); + gavin.getSession().put( "bar", new SessionAttribute( "bar", "foo bar baz 2" ) ); + } + ); + + scope.inTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + User gavin = (User) g.getUsers().get( "gavin" ); + User turin = (User) g.getUsers().get( "turin" ); + assertNotNull( gavin ); + assertNotNull( turin ); + assertNull( g.getUsers().get( "emmanuel" ) ); + assertFalse( Hibernate.isInitialized( g.getUsers() ) ); + assertNotNull( gavin.getSession().get( "foo" ) ); + assertNull( turin.getSession().get( "foo" ) ); + assertFalse( Hibernate.isInitialized( gavin.getSession() ) ); + assertFalse( Hibernate.isInitialized( turin.getSession() ) ); + session.delete( gavin ); + session.delete( turin ); + session.delete( g ); + } + ); + } + + @Test + public void testRemoveClear(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + User gavin = new User( "gavin", "secret" ); + User turin = new User( "turin", "tiger" ); + Group g = new Group( "developers" ); + g.getUsers().put( "gavin", gavin ); + g.getUsers().put( "turin", turin ); + session.persist( g ); + gavin.getSession().put( "foo", new SessionAttribute( "foo", "foo bar baz" ) ); + gavin.getSession().put( "bar", new SessionAttribute( "bar", "foo bar baz 2" ) ); + } + ); + + User turin = scope.fromTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + User gavin = (User) g.getUsers().get( "gavin" ); + User t = (User) g.getUsers().get( "turin" ); + assertFalse( Hibernate.isInitialized( g.getUsers() ) ); + g.getUsers().clear(); + gavin.getSession().remove( "foo" ); + assertTrue( Hibernate.isInitialized( g.getUsers() ) ); + assertTrue( Hibernate.isInitialized( gavin.getSession() ) ); + return t; + } + ); + scope.inTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + assertTrue( g.getUsers().isEmpty() ); + assertFalse( Hibernate.isInitialized( g.getUsers() ) ); + User gavin = session.get( User.class, "gavin" ); + assertFalse( gavin.getSession().containsKey( "foo" ) ); + assertFalse( Hibernate.isInitialized( gavin.getSession() ) ); + session.delete( gavin ); + session.delete( turin ); + session.delete( g ); + } + ); + } + + @Test + public void testIndexFormulaMap(SessionFactoryScope scope) { + User user1 = new User( "gavin", "secret" ); + User user2 = new User( "turin", "tiger" ); + scope.inTransaction( + session -> { + Group g = new Group( "developers" ); + g.getUsers().put( "gavin", user1 ); + g.getUsers().put( "turin", user2 ); + session.persist( g ); + user1.getSession().put( "foo", new SessionAttribute( "foo", "foo bar baz" ) ); + user1.getSession().put( "bar", new SessionAttribute( "bar", "foo bar baz 2" ) ); + } + ); + + scope.inTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + assertThat( g.getUsers().size(), is( 2 ) ); + g.getUsers().remove( "turin" ); + Map smap = ( (User) g.getUsers().get( "gavin" ) ).getSession(); + assertThat( smap.size(), is( 2 ) ); + smap.remove( "bar" ); + } + ); + + scope.inTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + assertThat( g.getUsers().size(), is( 1 ) ); + Map smap = ( (User) g.getUsers().get( "gavin" ) ).getSession(); + assertThat( smap.size(), is( 1 ) ); + User gavin = (User) g.getUsers().put( "gavin", user2 ); + session.delete( gavin ); + assertThat( + session.createQuery( "select count(*) from SessionAttribute" ).uniqueResult(), + is( 0L ) + ); + } + ); + + scope.inTransaction( + session -> { + Group g = session.get( Group.class, "developers" ); + assertThat( g.getUsers().size(), is( 1 ) ); + User turin = (User) g.getUsers().get( "turin" ); + Map smap = turin.getSession(); + assertThat( smap.size(), is( 0 ) ); + assertThat( session.createQuery( "select count(*) from User" ).uniqueResult(), is( 1L ) ); + session.delete( g ); + session.delete( turin ); + assertThat( session.createQuery( "select count(*) from User" ).uniqueResult(), is( 0L ) ); + } + ); + } + + @Test + @RequiresDialectFeature(feature = DialectFeatureChecks.DoubleQuoteQuoting.class) + public void testSQLQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + User gavin = new User( "gavin", "secret" ); + User turin = new User( "turin", "tiger" ); + gavin.getSession().put( "foo", new SessionAttribute( "foo", "foo bar baz" ) ); + gavin.getSession().put( "bar", new SessionAttribute( "bar", "foo bar baz 2" ) ); + session.persist( gavin ); + session.persist( turin ); + session.flush(); + session.clear(); + List results = session.getNamedQuery( "userSessionData" ).setParameter( "uname", "%in" ).list(); + assertThat( results.size(), is( 2 ) ); + gavin = (User) ( (Object[]) results.get( 0 ) )[0]; + assertThat( gavin.getName(), is( "gavin" ) ); + assertThat( gavin.getSession().size(), is( 2 ) ); + session.createQuery( "delete SessionAttribute" ).executeUpdate(); + session.createQuery( "delete User" ).executeUpdate(); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-4294") + public void testMap(SessionFactoryScope scope) { + Parent parent = new Parent(); + Child child = new Child(); + scope.inTransaction( + session -> { + child.setFirstName( "Ben" ); + parent.getChildren().put( child.getFirstName(), child ); + child.setParent( parent ); + session.save( parent ); + } + ); + // END PREPARE SECTION - - Session session2 = openSession(); - Parent parent2 = (Parent)session2.get(Parent.class, parent.getId()); - Child child2 = parent2.getChildren().get(child.getFirstName()); // causes SQLGrammarException because of wrong condition: where child0_.PARENT_ID=? and child0_.null=? - assertNotNull(child2); - session2.close(); + scope.inSession( + session -> { + Parent parent2 = session.get( Parent.class, parent.getId() ); + Child child2 = parent2.getChildren() + .get( child.getFirstName() ); // causes SQLGrammarException because of wrong condition: where child0_.PARENT_ID=? and child0_.null=? + assertNotNull( child2 ); + } + ); + } @Test @TestForIssue(jiraKey = "HHH-10874") - public void testWhereClauseOnBidirectionalCollection() { - Session s = openSession(); - Transaction t = s.beginTransaction(); + public void testWhereClauseOnBidirectionalCollection(SessionFactoryScope scope) { + School school = new School( 1 ); + Student gavin = new Student( "gavin", 4 ); + Student turin = new Student( "turin", 3 ); + Student mike = new Student( "mike", 5 ); + Student fred = new Student( "fred", 2 ); - School school = new School(1); - s.persist(school); + scope.inTransaction( + session -> { + session.persist( school ); - Student gavin = new Student("gavin", 4); - Student turin = new Student("turin", 3); - Student mike = new Student("mike", 5); - Student fred = new Student("fred", 2); + gavin.setSchool( school ); + turin.setSchool( school ); + mike.setSchool( school ); + fred.setSchool( school ); - gavin.setSchool(school); - turin.setSchool(school); - mike.setSchool(school); - fred.setSchool(school); + session.persist( gavin ); + session.persist( turin ); + session.persist( mike ); + session.persist( fred ); + } + ); - s.persist(gavin); - s.persist(turin); - s.persist(mike); - s.persist(fred); + scope.inSession( + session -> { + School school2 = session.get( School.class, 1 ); - t.commit(); - s.close(); + assertThat( school2.getStudents().size(), is( 4 ) ); - s = openSession(); - School school2 = s.get(School.class, 1); + assertThat( school2.getTopStudents().size(), is( 2 ) ); + assertTrue( school2.getTopStudents().contains( gavin ) ); + assertTrue( school2.getTopStudents().contains( mike ) ); - assertEquals(4, school2.getStudents().size()); - - assertEquals( 2, school2.getTopStudents().size() ); - assertTrue( school2.getTopStudents().contains( gavin ) ); - assertTrue( school2.getTopStudents().contains( mike ) ); - - assertEquals(2, school2.getStudentsMap().size() ); - assertTrue( school2.getStudentsMap().containsKey( gavin.getId() ) ); - assertTrue( school2.getStudentsMap().containsKey( mike.getId() ) ); - - s.close(); + assertThat( school2.getStudentsMap().size(), is( 2 ) ); + assertTrue( school2.getStudentsMap().containsKey( gavin.getId() ) ); + assertTrue( school2.getStudentsMap().containsKey( mike.getId() ) ); + } + ); } @Test - @FailureExpected( jiraKey = "HHH-3319" ) - public void testWhereClauseOnUnidirectionalCollection() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - + @FailureExpected(jiraKey = "HHH-3319") + public void testWhereClauseOnUnidirectionalCollection(SessionFactoryScope scope) { Championship championship = new Championship( 1 ); - s.persist(championship); + Student gavin = new Student( "gavin", 4 ); + Student turin = new Student( "turin", 3 ); + Student mike = new Student( "mike", 5 ); + Student fred = new Student( "fred", 2 ); - Student gavin = new Student("gavin", 4); - Student turin = new Student("turin", 3); - Student mike = new Student("mike", 5); - Student fred = new Student("fred", 2); + scope.inTransaction( + session -> { + session.persist( championship ); - championship.getStudents().add( gavin ); - championship.getStudents().add( turin ); - championship.getStudents().add( mike ); - championship.getStudents().add( fred ); + championship.getStudents().add( gavin ); + championship.getStudents().add( turin ); + championship.getStudents().add( mike ); + championship.getStudents().add( fred ); - s.persist(gavin); - s.persist(turin); - s.persist(mike); - s.persist(fred); + session.persist( gavin ); + session.persist( turin ); + session.persist( mike ); + session.persist( fred ); + } + ); - t.commit(); - s.close(); - - s = openSession(); - - Championship championship2 = s.get(Championship.class, 1); - assertEquals( 2, championship2.getStudents().size() ); - assertTrue( championship2.getStudents().contains( gavin ) ); - assertTrue( championship2.getStudents().contains( mike ) ); - - s.close(); + scope.inSession( + session -> { + Championship championship2 = session.get( Championship.class, 1 ); + assertThat( championship2.getStudents().size(), is( 2 ) ); + assertTrue( championship2.getStudents().contains( gavin ) ); + assertTrue( championship2.getStudents().contains( mike ) ); + } + ); } - @Override - protected boolean rebuildSessionFactoryOnError() { - return false; - } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java deleted file mode 100644 index f64ca53441..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/AbstractManyToManyAssociationClassTest.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.manytomanyassociationclass; -import java.util.HashSet; - -import org.junit.Test; - -import org.hibernate.Session; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -/** - * Abstract class for tests on many-to-many association using an association class. - * - * @author Gail Badner - */ -public abstract class AbstractManyToManyAssociationClassTest extends BaseCoreFunctionalTestCase { - private User user; - private Group group; - private Membership membership; - - public abstract Membership createMembership(String name); - - @Override - protected void prepareTest() { - Session s = openSession(); - s.beginTransaction(); - user = new User( "user" ); - group = new Group( "group" ); - s.save( user ); - s.save( group ); - membership = createMembership( "membership"); - addMembership( user, group, membership ); - s.getTransaction().commit(); - s.close(); - } - - @Override - protected void cleanupTest() { - if ( sessionFactory() != null ) { - Session s = openSession(); - s.beginTransaction(); - s.createQuery( "delete from " + membership.getClass().getName() ); - s.createQuery( "delete from User" ); - s.createQuery( "delete from Group" ); - s.getTransaction().commit(); - s.close(); - } - } - - public User getUser() { - return user; - } - - public Group getGroup() { - return group; - } - - public Membership getMembership() { - return membership; - } - - @Test - public void testRemoveAndAddSameElement() { - deleteMembership( user, group, membership ); - addMembership( user, group, membership ); - - Session s = openSession(); - s.beginTransaction(); - s.merge( user ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = ( User ) s.get( User.class, user.getId() ); - group = ( Group ) s.get( Group.class, group.getId() ); - membership = ( Membership ) s.get( membership.getClass(), membership.getId() ); - assertEquals( "user", user.getName() ); - assertEquals( "group", group.getName() ); - assertEquals( "membership", membership.getName() ); - assertEquals( 1, user.getMemberships().size() ); - assertEquals( 1, group.getMemberships().size() ); - assertSame( membership, user.getMemberships().iterator().next() ); - assertSame( membership, group.getMemberships().iterator().next() ); - assertSame( user, membership.getUser() ); - assertSame( group, membership.getGroup() ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testRemoveAndAddEqualElement() { - deleteMembership( user, group, membership ); - membership = createMembership( "membership" ); - addMembership( user, group, membership ); - - Session s = openSession(); - s.beginTransaction(); - s.merge( user ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = ( User ) s.get( User.class, user.getId() ); - group = ( Group ) s.get( Group.class, group.getId() ); - membership = ( Membership ) s.get( membership.getClass(), membership.getId() ); - assertEquals( "user", user.getName() ); - assertEquals( "group", group.getName() ); - assertEquals( "membership", membership.getName() ); - assertEquals( 1, user.getMemberships().size() ); - assertEquals( 1, group.getMemberships().size() ); - assertSame( membership, user.getMemberships().iterator().next() ); - assertSame( membership, group.getMemberships().iterator().next() ); - assertSame( user, membership.getUser() ); - assertSame( group, membership.getGroup() ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testRemoveAndAddEqualCollection() { - deleteMembership( user, group, membership ); - membership = createMembership( "membership" ); - user.setMemberships( new HashSet() ); - group.setMemberships( new HashSet() ); - addMembership( user, group, membership ); - - Session s = openSession(); - s.beginTransaction(); - s.merge( user ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = ( User ) s.get( User.class, user.getId() ); - group = ( Group ) s.get( Group.class, group.getId() ); - membership = ( Membership ) s.get( membership.getClass(), membership.getId() ); - assertEquals( "user", user.getName() ); - assertEquals( "group", group.getName() ); - assertEquals( "membership", membership.getName() ); - assertEquals( 1, user.getMemberships().size() ); - assertEquals( 1, group.getMemberships().size() ); - assertSame( membership, user.getMemberships().iterator().next() ); - assertSame( membership, group.getMemberships().iterator().next() ); - assertSame( user, membership.getUser() ); - assertSame( group, membership.getGroup() ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testRemoveAndAddSameElementNonKeyModified() { - deleteMembership( user, group, membership ); - addMembership( user, group, membership ); - membership.setName( "membership1" ); - - Session s = openSession(); - s.beginTransaction(); - s.merge( user ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = ( User ) s.get( User.class, user.getId() ); - group = ( Group ) s.get( Group.class, group.getId() ); - membership = ( Membership ) s.get( membership.getClass(), membership.getId() ); - assertEquals( "user", user.getName() ); - assertEquals( "group", group.getName() ); - assertEquals( "membership1", membership.getName() ); - assertEquals( 1, user.getMemberships().size() ); - assertEquals( 1, group.getMemberships().size() ); - assertSame( membership, user.getMemberships().iterator().next() ); - assertSame( membership, group.getMemberships().iterator().next() ); - assertSame( user, membership.getUser() ); - assertSame( group, membership.getGroup() ); - s.getTransaction().commit(); - s.close(); - - } - - @Test - public void testRemoveAndAddEqualElementNonKeyModified() { - deleteMembership( user, group, membership ); - membership = createMembership( "membership" ); - addMembership( user, group, membership ); - membership.setName( "membership1" ); - - Session s = openSession(); - s.beginTransaction(); - s.merge( user ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - user = ( User ) s.get( User.class, user.getId() ); - group = ( Group ) s.get( Group.class, group.getId() ); - membership = ( Membership ) s.get( membership.getClass(), membership.getId() ); - assertEquals( "user", user.getName() ); - assertEquals( "group", group.getName() ); - assertEquals( "membership1", membership.getName() ); - assertEquals( 1, user.getMemberships().size() ); - assertEquals( 1, group.getMemberships().size() ); - assertSame( membership, user.getMemberships().iterator().next() ); - assertSame( membership, group.getMemberships().iterator().next() ); - assertSame( user, membership.getUser() ); - assertSame( group, membership.getGroup() ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testDeleteDetached() { - Session s = openSession(); - s.beginTransaction(); - s.delete( user ); - s.delete( group ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - assertNull( s.get( User.class, user.getId() ) ); - assertNull( s.get( Group.class , group.getId() ) ); - assertNull( s.get( membership.getClass(), membership.getId() ) ); - s.getTransaction().commit(); - s.close(); - } - - public void deleteMembership(User u, Group g, Membership ug) { - if ( u == null || g == null ) { - throw new IllegalArgumentException(); - } - u.getMemberships().remove( ug ); - g.getMemberships().remove( ug ); - ug.setUser( null ); - ug.setGroup( null ); - } - - public void addMembership(User u, Group g, Membership ug) { - if ( u == null || g == null ) { - throw new IllegalArgumentException(); - } - ug.setUser( u ); - ug.setGroup( g ); - u.getMemberships().add( ug ); - g.getMemberships().add( ug ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java deleted file mode 100644 index c3ab40350f..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/manytomanyassociationclass/surrogateid/generated/ManyToManyAssociationClassGeneratedIdTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.manytomanyassociationclass.surrogateid.generated; - -import javax.persistence.PersistenceException; -import java.util.HashSet; - -import org.hibernate.Session; -import org.hibernate.exception.ConstraintViolationException; - -import org.hibernate.test.manytomanyassociationclass.AbstractManyToManyAssociationClassTest; -import org.hibernate.test.manytomanyassociationclass.Membership; -import org.junit.Test; - -import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.fail; - -/** - * Tests on many-to-many association using an association class with a surrogate ID that is generated. - * - * @author Gail Badner - */ -public class ManyToManyAssociationClassGeneratedIdTest extends AbstractManyToManyAssociationClassTest { - @Override - public String[] getMappings() { - return new String[] { "manytomanyassociationclass/surrogateid/generated/Mappings.hbm.xml" }; - } - - @Override - public Membership createMembership(String name) { - return new Membership( name ); - } - - @Test - public void testRemoveAndAddEqualElement() { - deleteMembership( getUser(), getGroup(), getMembership() ); - addMembership( getUser(), getGroup(), createMembership( "membership" ) ); - - Session s = openSession(); - s.beginTransaction(); - try { - // The new membership is transient (it has a null surrogate ID), so - // Hibernate assumes that it should be added to the collection. - // Inserts are done before deletes, so a ConstraintViolationException - // will be thrown on the insert because the unique constraint on the - // user and group IDs in the join table is violated. See HHH-2801. - s.merge( getUser() ); - s.getTransaction().commit(); - fail( "should have failed because inserts are before deletes"); - } - catch (PersistenceException e) { - s.getTransaction().rollback(); - // expected - assertTyping( ConstraintViolationException.class, e.getCause() ); - } - finally { - s.close(); - } - } - - @Test - public void testRemoveAndAddEqualCollection() { - deleteMembership( getUser(), getGroup(), getMembership() ); - getUser().setMemberships( new HashSet() ); - getGroup().setMemberships( new HashSet() ); - addMembership( getUser(), getGroup(), createMembership( "membership" ) ); - - Session s = openSession(); - s.beginTransaction(); - try { - // The new membership is transient (it has a null surrogate ID), so - // Hibernate assumes that it should be added to the collection. - // Inserts are done before deletes, so a ConstraintViolationException - // will be thrown on the insert because the unique constraint on the - // user and group IDs in the join table is violated. See HHH-2801. - s.merge( getUser() ); - s.getTransaction().commit(); - fail( "should have failed because inserts are before deletes"); - } - catch (PersistenceException e) { - s.getTransaction().rollback(); - // expected - assertTyping( ConstraintViolationException.class, e.getCause() ); - } - finally { - s.close(); - } - } - - @Test - public void testRemoveAndAddEqualElementNonKeyModified() { - deleteMembership( getUser(), getGroup(), getMembership() ); - Membership membershipNew = createMembership( "membership" ); - addMembership( getUser(), getGroup(), membershipNew ); - membershipNew.setName( "membership1" ); - - Session s = openSession(); - s.beginTransaction(); - try { - // The new membership is transient (it has a null surrogate ID), so - // Hibernate assumes that it should be added to the collection. - // Inserts are done before deletes, so a ConstraintViolationException - // will be thrown on the insert because the unique constraint on the - // user and group IDs in the join table is violated. See HHH-2801. - s.merge( getUser() ); - s.getTransaction().commit(); - fail( "should have failed because inserts are before deletes"); - } - catch (PersistenceException e) { - s.getTransaction().rollback(); - // expected - assertTyping( ConstraintViolationException.class, e.getCause() ); - } - finally { - s.close(); - } - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/OnDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/ondelete/OnDeleteTest.java deleted file mode 100755 index 5bce33d587..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/OnDeleteTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ondelete; - -import java.util.List; - -import org.junit.Test; - -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.stat.Statistics; -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - - -/** - * @author Gavin King - */ -public class OnDeleteTest extends BaseCoreFunctionalTestCase { - @Override - public String[] getMappings() { - return new String[] { "ondelete/Person.hbm.xml" }; - } - - @Override - public void configure(Configuration cfg) { - cfg.setProperty(Environment.GENERATE_STATISTICS, "true"); - } - - @Test - @RequiresDialectFeature( - value = DialectChecks.SupportsCircularCascadeDeleteCheck.class, - comment = "db/dialect does not support circular cascade delete constraints" - ) - public void testJoinedSubclass() { - Statistics statistics = sessionFactory().getStatistics(); - statistics.clear(); - - Session s = openSession(); - Transaction t = s.beginTransaction(); - - Salesperson mark = new Salesperson(); - mark.setName("Mark"); - mark.setTitle("internal sales"); - mark.setSex('M'); - mark.setAddress("buckhead"); - mark.setZip("30305"); - mark.setCountry("USA"); - - Person joe = new Person(); - joe.setName("Joe"); - joe.setAddress("San Francisco"); - joe.setZip("XXXXX"); - joe.setCountry("USA"); - joe.setSex('M'); - joe.setSalesperson(mark); - mark.getCustomers().add(joe); - - s.save(mark); - - t.commit(); - - assertEquals( statistics.getEntityInsertCount(), 2 ); - assertEquals( statistics.getPrepareStatementCount(), 5 ); - - statistics.clear(); - - t = s.beginTransaction(); - s.delete(mark); - t.commit(); - - assertEquals( statistics.getEntityDeleteCount(), 2 ); - if ( getDialect().supportsCascadeDelete() ) { - assertEquals( statistics.getPrepareStatementCount(), 1 ); - } - - t = s.beginTransaction(); - List names = s.createQuery("select name from Person").list(); - assertTrue( names.isEmpty() ); - t.commit(); - - s.close(); - } - -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/ToOneOnDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/ToOneOnDeleteTest.java deleted file mode 100644 index f7b603dd95..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/ToOneOnDeleteTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.hibernate.test.ondelete.toone; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; - -import org.hibernate.Session; -import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; -import org.hibernate.dialect.SybaseDialect; - -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.junit.Test; - -/** - * @author Vlad Mihalcea - */ -public class ToOneOnDeleteTest extends BaseNonConfigCoreFunctionalTestCase { - - @Test - @SkipForDialect( - value = SybaseDialect.class, - jiraKey = "HHH-13559", - comment = "on-delete=\"cascade\" is not supported for unidirectional to-one associations using Sybase" - ) - public void testManyToOne() throws Exception { - Session session = openSession(); - session.getTransaction().begin(); - - Parent parent = new Parent(); - parent.id = 1L; - session.persist( parent ); - - Child child1 = new Child(); - child1.id = 1L; - child1.parent = parent; - session.persist( child1 ); - - GrandChild grandChild11 = new GrandChild(); - grandChild11.id = 1L; - grandChild11.parent = child1; - session.persist( grandChild11 ); - - Child child2 = new Child(); - child2.id = 2L; - child2.parent = parent; - session.persist( child2 ); - - GrandChild grandChild21 = new GrandChild(); - grandChild21.id = 2L; - grandChild21.parent = child2; - session.persist( grandChild21 ); - - GrandChild grandChild22 = new GrandChild(); - grandChild22.id = 3L; - grandChild22.parent = child2; - session.persist( grandChild22 ); - - session.getTransaction().commit(); - session.close(); - - session = openSession(); - session.getTransaction().begin(); - - parent = session.get( Parent.class, 1L ); - session.delete( parent ); - - session.getTransaction().commit(); - session.close(); - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Parent.class, - Child.class, - GrandChild.class - }; - } - - @Entity(name = "Parent") - public static class Parent { - - @Id - private Long id; - } - - @Entity(name = "Child") - public static class Child { - - @Id - private Long id; - - @ManyToOne - @OnDelete(action = OnDeleteAction.CASCADE) - private Parent parent; - } - - @Entity(name = "GrandChild") - public static class GrandChild { - - @Id - private Long id; - - @OneToOne - @OnDelete(action = OnDeleteAction.CASCADE) - private Child parent; - } -} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java b/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java deleted file mode 100644 index 7ac3f1d5db..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ondelete/toone/hbm/ToOneOnDeleteHbmTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ondelete.toone.hbm; - -import org.hibernate.Session; -import org.hibernate.dialect.SybaseDialect; - -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -/** - * @author Vlad Mihalcea - */ -public class ToOneOnDeleteHbmTest extends BaseCoreFunctionalTestCase { - - @Test - @SkipForDialect( - value = SybaseDialect.class, - jiraKey = "HHH-13559", - comment = "on-delete=\"cascade\" is not supported for unidirectional to-one associations using Sybase" - ) - public void testManyToOne() throws Exception { - Session session = openSession(); - session.getTransaction().begin(); - - Parent parent = new Parent(); - parent.setId( 1L ); - session.persist( parent ); - - Child child1 = new Child(); - child1.setId( 1L ); - child1.setParent( parent ); - session.persist( child1 ); - - GrandChild grandChild11 = new GrandChild(); - grandChild11.setId( 1L ); - grandChild11.setParent( child1 ); - session.persist( grandChild11 ); - - Child child2 = new Child(); - child2.setId( 2L ); - child2.setParent( parent ); - session.persist( child2 ); - - GrandChild grandChild21 = new GrandChild(); - grandChild21.setId( 2L ); - grandChild21.setParent( child2 ); - session.persist( grandChild21 ); - - session.getTransaction().commit(); - session.close(); - - session = openSession(); - session.getTransaction().begin(); - - parent = session.get( Parent.class, 1L ); - session.delete( parent ); - - session.getTransaction().commit(); - session.close(); - } - - @Override - public String[] getMappings() { - return new String[] { "ondelete/toone/hbm/ToOneOnDelete.hbm.xml" }; - } - -} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/LazyLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/ondemandload/LazyLoadingTest.java deleted file mode 100644 index 71a3663165..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/LazyLoadingTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ - -package org.hibernate.test.ondemandload; - -import java.math.BigDecimal; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class LazyLoadingTest extends BaseCoreFunctionalTestCase { - - @Before - public void setUpData() { - Session s = openSession(); - s.beginTransaction(); - Store store = new Store( 1 ) - .setName( "Acme Super Outlet" ); - s.persist( store ); - - Product product = new Product( "007" ) - .setName( "widget" ) - .setDescription( "FooBar" ); - s.persist( product ); - - store.addInventoryProduct( product ) - .setQuantity( 10L ) - .setStorePrice( new BigDecimal( 500 ) ); - - s.getTransaction().commit(); - s.close(); - } - - @After - public void cleanUpData() { - Session s = openSession(); - s.beginTransaction(); - s.delete( s.get( Store.class, 1 ) ); - s.delete( s.get( Product.class, "007" ) ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testLazyCollectionLoadingWithClearedSession() { - sessionFactory().getStatistics().clear(); - - Session s = openSession(); - s.beginTransaction(); - // first load the store, making sure collection is not initialized - Store store = (Store) s.get( Store.class, 1 ); - assertNotNull( store ); - assertFalse( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 0, sessionFactory().getStatistics().getSessionCloseCount() ); - - // then clear session and try to initialize collection - s.clear(); - store.getInventories().size(); - assertTrue( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); - - s.clear(); - store = (Store) s.get( Store.class, 1 ); - assertNotNull( store ); - assertFalse( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); - - s.clear(); - store.getInventories().iterator(); - assertTrue( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); - - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testLazyCollectionLoadingWithClosedSession() { - sessionFactory().getStatistics().clear(); - - Session s = openSession(); - s.beginTransaction(); - // first load the store, making sure collection is not initialized - Store store = (Store) s.get( Store.class, 1 ); - assertNotNull( store ); - assertFalse( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 0, sessionFactory().getStatistics().getSessionCloseCount() ); - - // close the session and try to initialize collection - s.getTransaction().commit(); - s.close(); - - assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); - - store.getInventories().size(); - assertTrue( Hibernate.isInitialized( store.getInventories() ) ); - - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); - } - - @Test - public void testLazyEntityLoadingWithClosedSession() { - sessionFactory().getStatistics().clear(); - - Session s = openSession(); - s.beginTransaction(); - // first load the store, making sure it is not initialized - Store store = (Store) s.load( Store.class, 1 ); - assertNotNull( store ); - assertFalse( Hibernate.isInitialized( store ) ); - - assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 0, sessionFactory().getStatistics().getSessionCloseCount() ); - - // close the session and try to initialize store - s.getTransaction().commit(); - s.close(); - - assertEquals( 1, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); - - store.getName(); - assertTrue( Hibernate.isInitialized( store ) ); - - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); - } - - @Override - protected void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" ); - cfg.setProperty( Environment.GENERATE_STATISTICS, "true" ); - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Store.class, - Inventory.class, - Product.class - }; - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/cache/CacheLazyLoadNoTransTest.java b/hibernate-core/src/test/java/org/hibernate/test/ondemandload/cache/CacheLazyLoadNoTransTest.java deleted file mode 100644 index 404025a349..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ondemandload/cache/CacheLazyLoadNoTransTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ondemandload.cache; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import javax.persistence.Cacheable; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Table; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.annotations.Cache; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.cache.spi.access.CollectionDataAccess; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Environment; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.persister.collection.CollectionPersister; - -import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Janario Oliveira - */ -public class CacheLazyLoadNoTransTest extends BaseNonConfigCoreFunctionalTestCase { - - @SuppressWarnings("unchecked") - @Override - protected void addSettings(Map settings) { - super.addSettings( settings ); - - settings.put( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, "true" ); - settings.put( Environment.USE_SECOND_LEVEL_CACHE, "true" ); - settings.put( Environment.USE_QUERY_CACHE, "true" ); - settings.put( Environment.CACHE_PROVIDER_CONFIG, "true" ); - } - - @Test - public void hibernateInitialize() { - Customer customer = new Customer(); - Item item1 = new Item( customer ); - Item item2 = new Item( customer ); - customer.boughtItems.add( item1 ); - customer.boughtItems.add( item2 ); - persist( customer ); - - customer = find( Customer.class, customer.id ); - assertFalse( Hibernate.isInitialized( customer.boughtItems ) ); - Hibernate.initialize( customer.boughtItems ); - assertTrue( Hibernate.isInitialized( customer.boughtItems ) ); - } - - @Test - public void testOneToMany() { - Customer customer = new Customer(); - Item item1 = new Item( customer ); - Item item2 = new Item( customer ); - customer.boughtItems.add( item1 ); - customer.boughtItems.add( item2 ); - persist( customer ); - - //init cache - assertFalse( isCached( customer.id, Customer.class, "boughtItems" ) ); - customer = find( Customer.class, customer.id ); - assertEquals( 2, customer.boughtItems.size() ); - - //read from cache - assertTrue( isCached( customer.id, Customer.class, "boughtItems" ) ); - customer = find( Customer.class, customer.id ); - assertEquals( 2, customer.boughtItems.size() ); - } - - @Test - public void testManyToMany() { - Application application = new Application(); - persist( application ); - Customer customer = new Customer(); - customer.applications.add( application ); - application.customers.add( customer ); - persist( customer ); - - //init cache - assertFalse( isCached( customer.id, Customer.class, "applications" ) ); - assertFalse( isCached( application.id, Application.class, "customers" ) ); - - customer = find( Customer.class, customer.id ); - assertEquals( 1, customer.applications.size() ); - application = find( Application.class, application.id ); - assertEquals( 1, application.customers.size() ); - - assertTrue( isCached( customer.id, Customer.class, "applications" ) ); - assertTrue( isCached( application.id, Application.class, "customers" ) ); - - //read from cache - customer = find( Customer.class, customer.id ); - assertEquals( 1, customer.applications.size() ); - application = find( Application.class, application.id ); - assertEquals( 1, application.customers.size() ); - } - - private void persist(Object entity) { - Session session = openSession(); - session.beginTransaction(); - session.persist( entity ); - session.getTransaction().commit(); - session.close(); - } - - private E find(Class entityClass, int id) { - Session session; - session = openSession(); - E customer = session.get( entityClass, id ); - session.close(); - return customer; - } - - private boolean isCached(Serializable id, Class entityClass, String attr) { - Session session = openSession(); - CollectionPersister persister = sessionFactory().getCollectionPersister( entityClass.getName() + "." + attr ); - CollectionDataAccess cache = persister.getCacheAccessStrategy(); - Object key = cache.generateCacheKey( id, persister, sessionFactory(), session.getTenantIdentifier() ); - Object cachedValue = cache.get( ( (SessionImplementor) session ), key ); - session.close(); - return cachedValue != null; - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] {Application.class, Customer.class, Item.class}; - } - - @Entity - @Table(name = "application") - @Cacheable - public static class Application { - @Id - @GeneratedValue - private Integer id; - - @ManyToMany(mappedBy = "applications") - @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - private List customers = new ArrayList<>(); - } - - @Entity - @Table(name = "customer") - @Cacheable - @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - public static class Customer { - @Id - @GeneratedValue - private Integer id; - - @ManyToMany - @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - private List applications = new ArrayList<>(); - - @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) - @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - private List boughtItems = new ArrayList<>(); - } - - @Entity - @Table(name = "item") - @Cacheable - @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - public static class Item { - @Id - @GeneratedValue - private Integer id; - @ManyToOne - @JoinColumn(name = "customer_id") - private Customer customer; - - protected Item() { - } - - public Item(Customer customer) { - this.customer = customer; - } - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java deleted file mode 100644 index f2badbee5a..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/AbstractOperationTestCase.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractOperationTestCase extends BaseCoreFunctionalTestCase { - public void configure(Configuration cfg) { - cfg.setProperty( Environment.GENERATE_STATISTICS, "true"); - cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" ); - } - - public String[] getMappings() { - return new String[] { - "ops/Node.hbm.xml", - "ops/Employer.hbm.xml", - "ops/OptLockEntity.hbm.xml", - "ops/OneToOne.hbm.xml", - "ops/Competition.hbm.xml" - }; - } - - public String getCacheConcurrencyStrategy() { - return null; - } - - protected void clearCounts() { - sessionFactory().getStatistics().clear(); - } - - protected void assertInsertCount(int expected) { - int inserts = ( int ) sessionFactory().getStatistics().getEntityInsertCount(); - assertEquals( "unexpected insert count", expected, inserts ); - } - - protected void assertUpdateCount(int expected) { - int updates = ( int ) sessionFactory().getStatistics().getEntityUpdateCount(); - assertEquals( "unexpected update counts", expected, updates ); - } - - protected void assertDeleteCount(int expected) { - int deletes = ( int ) sessionFactory().getStatistics().getEntityDeleteCount(); - assertEquals( "unexpected delete counts", expected, deletes ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java deleted file mode 100755 index b992eaae51..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/CreateTest.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import javax.persistence.PersistenceException; -import java.util.ArrayList; -import java.util.Collection; - -import org.hibernate.PersistentObjectException; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.dialect.AbstractHANADialect; -import org.hibernate.exception.ConstraintViolationException; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.SkipForDialect; -import org.junit.Test; - -import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -/** - * @author Gavin King - */ -@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class) -public class CreateTest extends AbstractOperationTestCase { - @Test - @SuppressWarnings( {"unchecked"}) - public void testNoUpdatesOnCreateVersionedWithCollection() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - VersionedEntity root = new VersionedEntity( "root", "root" ); - VersionedEntity child = new VersionedEntity( "c1", "child-1" ); - root.getChildren().add( child ); - child.setParent( root ); - s.save(root); - tx.commit(); - s.close(); - - assertInsertCount( 2 ); - assertUpdateCount( 0 ); - assertDeleteCount( 0 ); - - s = openSession(); - tx = s.beginTransaction(); - s.delete( root ); - tx.commit(); - s.close(); - - assertUpdateCount( 0 ); - assertDeleteCount( 2 ); - } - - @Test - public void testCreateTree() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node("root"); - Node child = new Node("child"); - root.addChild(child); - s.persist(root); - tx.commit(); - s.close(); - - assertInsertCount(2); - assertUpdateCount(0); - - s = openSession(); - tx = s.beginTransaction(); - System.out.println("getting"); - root = (Node) s.get(Node.class, "root"); - Node child2 = new Node("child2"); - root.addChild(child2); - System.out.println("committing"); - tx.commit(); - s.close(); - - assertInsertCount(3); - assertUpdateCount(0); - } - - @Test - public void testCreateTreeWithGeneratedId() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode("root"); - NumberedNode child = new NumberedNode("child"); - root.addChild(child); - s.persist(root); - tx.commit(); - s.close(); - - assertInsertCount(2); - assertUpdateCount(0); - - s = openSession(); - tx = s.beginTransaction(); - root = (NumberedNode) s.get( NumberedNode.class, Long.valueOf( root.getId() ) ); - NumberedNode child2 = new NumberedNode("child2"); - root.addChild(child2); - tx.commit(); - s.close(); - - assertInsertCount(3); - assertUpdateCount(0); - } - - @Test - public void testCreateException() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node dupe = new Node("dupe"); - s.persist(dupe); - s.persist(dupe); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - s.persist(dupe); - try { - tx.commit(); - fail( "Expecting constraint failure" ); - } - catch (PersistenceException e){ - //verify that an exception is thrown! - assertTyping(ConstraintViolationException.class, e.getCause()); - } - tx.rollback(); - s.close(); - - Node nondupe = new Node("nondupe"); - nondupe.addChild(dupe); - - s = openSession(); - tx = s.beginTransaction(); - s.persist(nondupe); - try { - tx.commit(); - assertFalse(true); - } - catch (PersistenceException e){ - //verify that an exception is thrown! - assertTyping(ConstraintViolationException.class, e.getCause()); - } - tx.rollback(); - s.close(); - } - - @Test - public void testCreateExceptionWithGeneratedId() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode dupe = new NumberedNode("dupe"); - s.persist(dupe); - s.persist(dupe); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - try { - s.persist(dupe); - assertFalse(true); - } - catch (PersistenceException e){ - //verify that an exception is thrown! - assertTyping(PersistentObjectException.class, e.getCause()); - } - tx.rollback(); - s.close(); - - NumberedNode nondupe = new NumberedNode("nondupe"); - nondupe.addChild(dupe); - - s = openSession(); - tx = s.beginTransaction(); - try { - s.persist(nondupe); - assertFalse(true); - } - catch (PersistenceException e){ - //verify that an exception is thrown! - assertTyping(PersistentObjectException.class, e.getCause()); - } - tx.rollback(); - s.close(); - } - - @Test - @SuppressWarnings( {"unchecked"}) - @SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column") - public void testBasic() throws Exception { - Session s; - Transaction tx; - s = openSession(); - tx = s.beginTransaction(); - Employer er = new Employer(); - Employee ee = new Employee(); - s.persist(ee); - Collection erColl = new ArrayList(); - Collection eeColl = new ArrayList(); - erColl.add(ee); - eeColl.add(er); - er.setEmployees(erColl); - ee.setEmployers(eeColl); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - er = (Employer) s.load(Employer.class, er.getId() ); - assertNotNull(er); - assertNotNull( er.getEmployees() ); - assertEquals( 1, er.getEmployees().size() ); - Employee eeFromDb = (Employee) er.getEmployees().iterator().next(); - assertEquals( ee.getId(), eeFromDb.getId() ); - tx.commit(); - s.close(); - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/DeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/DeleteTest.java deleted file mode 100644 index 5a0ac600d0..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/DeleteTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.junit.Test; - -import org.hibernate.Session; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; - -/** - * @author Steve Ebersole - */ -@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class) -public class DeleteTest extends AbstractOperationTestCase { - @Test - @SuppressWarnings( {"unchecked"}) - public void testDeleteVersionedWithCollectionNoUpdate() { - // test adapted from HHH-1564... - Session s = openSession(); - s.beginTransaction(); - VersionedEntity c = new VersionedEntity( "c1", "child-1" ); - VersionedEntity p = new VersionedEntity( "root", "root"); - p.getChildren().add( c ); - c.setParent( p ); - s.save( p ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - s = openSession(); - s.beginTransaction(); - VersionedEntity loadedParent = ( VersionedEntity ) s.get( VersionedEntity.class, "root" ); - s.delete( loadedParent ); - s.getTransaction().commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - assertDeleteCount( 2 ); - } - - @Test - public void testNoUpdateOnDelete() { - Session s = openSession(); - s.beginTransaction(); - Node node = new Node( "test" ); - s.persist( node ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - s = openSession(); - s.beginTransaction(); - s.delete( node ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - } - - @Test - @SuppressWarnings( {"unchecked"}) - public void testNoUpdateOnDeleteWithCollection() { - Session s = openSession(); - s.beginTransaction(); - Node parent = new Node( "parent" ); - Node child = new Node( "child" ); - parent.getCascadingChildren().add( child ); - s.persist( parent ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - s = openSession(); - s.beginTransaction(); - parent = ( Node ) s.get( Node.class, "parent" ); - s.delete( parent ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - assertDeleteCount( 2 ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/GetLoadTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/GetLoadTest.java deleted file mode 100644 index 72f29a0a65..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/GetLoadTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - - -/** - * @author Gavin King - */ -@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class) -public class GetLoadTest extends BaseCoreFunctionalTestCase { - @Override - public void configure(Configuration cfg) { - cfg.setProperty(Environment.GENERATE_STATISTICS, "true"); - cfg.setProperty(Environment.STATEMENT_BATCH_SIZE, "0"); - } - - @Override - public String[] getMappings() { - return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml" }; - } - - @Test - public void testGetLoad() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Employer emp = new Employer(); - s.persist(emp); - Node node = new Node("foo"); - Node parent = new Node("bar"); - parent.addChild(node); - s.persist(parent); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - emp = (Employer) s.get(Employer.class, emp.getId()); - assertTrue( Hibernate.isInitialized(emp) ); - assertFalse( Hibernate.isInitialized(emp.getEmployees()) ); - node = (Node) s.get(Node.class, node.getName()); - assertTrue( Hibernate.isInitialized(node) ); - assertFalse( Hibernate.isInitialized(node.getChildren()) ); - assertFalse( Hibernate.isInitialized(node.getParent()) ); - assertNull( s.get(Node.class, "xyz") ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - emp = (Employer) s.load(Employer.class, emp.getId()); - emp.getId(); - assertFalse( Hibernate.isInitialized(emp) ); - node = (Node) s.load(Node.class, node.getName()); - assertEquals( node.getName(), "foo" ); - assertFalse( Hibernate.isInitialized(node) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - emp = (Employer) s.get("org.hibernate.test.ops.Employer", emp.getId()); - assertTrue( Hibernate.isInitialized(emp) ); - node = (Node) s.get("org.hibernate.test.ops.Node", node.getName()); - assertTrue( Hibernate.isInitialized(node) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - emp = (Employer) s.load("org.hibernate.test.ops.Employer", emp.getId()); - emp.getId(); - assertFalse( Hibernate.isInitialized(emp) ); - node = (Node) s.load("org.hibernate.test.ops.Node", node.getName()); - assertEquals( node.getName(), "foo" ); - assertFalse( Hibernate.isInitialized(node) ); - tx.commit(); - s.close(); - - assertFetchCount(0); - } - - @Test - public void testGetAfterDelete() { - clearCounts(); - - Session s = openSession(); - s.beginTransaction(); - Employer emp = new Employer(); - s.persist( emp ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.beginTransaction(); - s.delete( emp ); - emp = s.get( Employer.class, emp.getId() ); - s.getTransaction().commit(); - s.close(); - - assertNull( "get did not return null after delete", emp ); - } - - private void clearCounts() { - sessionFactory().getStatistics().clear(); - } - - private void assertFetchCount(int count) { - int fetches = (int) sessionFactory().getStatistics().getEntityFetchCount(); - assertEquals(count, fetches); - } - - -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java deleted file mode 100644 index 9d7d3d8647..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/HANANoColumnInsertTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.hibernate.MappingException; -import org.hibernate.dialect.AbstractHANADialect; - -import org.hibernate.testing.RequiresDialect; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Vlad Mihalcea - */ -@RequiresDialect(value = { AbstractHANADialect.class }) -public class HANANoColumnInsertTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[]{ - "ops/Competition.hbm.xml" - }; - } - - @Override - protected void buildSessionFactory() { - try { - super.buildSessionFactory(); - - fail( "Should have thrown MappingException!" ); - } - catch (MappingException e) { - assertEquals( - "The INSERT statement for table [Competition] contains no column, and this is not supported by [" + getDialect().getClass().getName() + "]", - e.getMessage() ); - } - } - - @Test - public void test() throws Exception { - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java deleted file mode 100644 index db0bde8527..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedOrphanDeleteTest.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import java.util.List; - -import org.junit.Test; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Tests merging multiple detached representations of the same entity (allowed) - * where some associations include cascade="delete-orphan" - * - * @author Gail Badner - */ -public class MergeMultipleEntityCopiesAllowedOrphanDeleteTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[] { - "ops/HoarderOrphanDelete.hbm.xml" - }; - } - - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( - "hibernate.event.merge.entity_copy_observer", - "allow" - ); - } - - @Test - @FailureExpected( jiraKey = "HHH-9240" ) - public void testTopLevelUnidirOneToManyBackrefWithNewElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); - - Category category = new Category(); - category.setName( "category" ); - - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - // The following will fail due to PropertyValueException because item1 will - // be removed from the inverted merge map when the operation cascades to item1_1. - Item item1Merged = (Item) s.merge( item1 ); - // top-level collection should win - assertEquals( 2, item1.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 2, item1.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyBackrefWithNewElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getSubItemsBackref() ); - tx.commit(); - s.close(); - - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - - // Add a new SubItem to the Item representation that will be in a nested association. - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1_1.getSubItemsBackref().add( subItem2 ); - - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // The resulting collection should contain the added element - assertEquals( 2, item1Merged.getSubItemsBackref().size() ); - assertEquals( "subItem1 name", item1Merged.getSubItemsBackref().get( 0 ).getName() ); - assertEquals( "subItem2 name", item1Merged.getSubItemsBackref().get( 1 ).getName() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 2, item1.getSubItemsBackref().size() ); - assertEquals( "subItem1 name", item1.getSubItemsBackref().get( 0 ).getName() ); - assertEquals( "subItem2 name", item1.getSubItemsBackref().get( 1 ).getName() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyBackrefWithRemovedElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); - - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - // remove subItem1 from top-level Item - item1.getSubItemsBackref().remove( subItem1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // element should be removed - assertEquals( 1, item1Merged.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getSubItemsBackref().size() ); - // because cascade includes "delete-orphan" the removed SubItem should have been deleted. - subItem1 = (SubItem) s.get( SubItem.class, subItem1.getId() ); - assertNull( subItem1 ); - tx.commit(); - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyBackrefWithRemovedElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getSubItemsBackref() ); - tx.commit(); - s.close(); - - // remove subItem1 from the nested Item - item1_1.getSubItemsBackref().remove( subItem1 ); - - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the element should have been removed - assertEquals( 1, item1Merged.getSubItemsBackref().size() ); - assertTrue( item1Merged.getSubItemsBackref().contains( subItem2 ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getSubItemsBackref().size() ); - assertTrue( item1.getSubItemsBackref().contains( subItem2 ) ); - // because cascade includes "delete-orphan" the removed SubItem should have been deleted. - subItem1 = (SubItem) s.get( SubItem.class, subItem1.getId() ); - assertNull( subItem1 ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyNoBackrefWithNewElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); - - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 2, category1Merged.getSubCategories().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 2, category1.getSubCategories().size() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyNoBackrefWithNewElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - Hibernate.initialize( category1_1.getSubCategories() ); - tx.commit(); - s.close(); - - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1_1.getSubCategories().add( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - // new element should be there - assertEquals( 2, category1Merged.getSubCategories().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 2, category1.getSubCategories().size() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyNoBackrefWithRemovedElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - category1.getSubCategories().remove( subCategory1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 1, category1Merged.getSubCategories().size() ); - assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 1, category1.getSubCategories().size() ); - assertTrue( category1.getSubCategories().contains( subCategory2 ) ); - subCategory1 = (SubCategory) s.get( SubCategory.class, subCategory1.getId() ); - assertNull( subCategory1 ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyNoBackrefWithRemovedElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - Hibernate.initialize( category1_1.getSubCategories() ); - tx.commit(); - s.close(); - - category1_1.getSubCategories().remove( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 1, category1Merged.getSubCategories().size() ); - assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 1, category1.getSubCategories().size() ); - assertTrue( category1.getSubCategories().contains( subCategory2 ) ); - subCategory1 = (SubCategory) s.get( SubCategory.class, subCategory1.getId() ); - assertNull( subCategory1 ); - tx.commit(); - s.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - Session s = openSession(); - s.beginTransaction(); - - s.createQuery( "delete from SubItem" ).executeUpdate(); - for ( Hoarder hoarder : (List) s.createQuery( "from Hoarder" ).list() ) { - hoarder.getItems().clear(); - s.delete( hoarder ); - } - - for ( Category category : (List) s.createQuery( "from Category" ).list() ) { - if ( category.getExampleItem() != null ) { - category.setExampleItem( null ); - s.delete( category ); - } - } - - for ( Item item : (List) s.createQuery( "from Item" ).list() ) { - item.setCategory( null ); - s.delete( item ); - } - - s.createQuery( "delete from Item" ).executeUpdate(); - - s.getTransaction().commit(); - s.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedTest.java deleted file mode 100644 index ce49f4fc20..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesAllowedTest.java +++ /dev/null @@ -1,1208 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import javax.persistence.PersistenceException; -import java.util.List; - -import org.junit.Test; - -import org.hibernate.Hibernate; -import org.hibernate.PersistentObjectException; -import org.hibernate.Session; -import org.hibernate.StaleObjectStateException; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.testing.FailureExpected; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Tests merging multiple detached representations of the same entity when explicitly allowed. - * - * @author Gail Badner - */ -public class MergeMultipleEntityCopiesAllowedTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[] { - "ops/Hoarder.hbm.xml" - }; - } - - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( - "hibernate.event.merge.entity_copy_observer", - "allow" - ); - } - - @Test - public void testNestedDiffBasicProperty() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // change basic property of nested entity - item1_1.setName( "item1_1 name" ); - - // change the nested Item to be the copy with the new name - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the name from the top level item will win. - assertEquals( item1.getName(), item1Merged.getName() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Get = (Item) s.get( Item.class, item1.getId() ); - assertEquals( item1.getName(), item1Get.getName() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testNestedManyToOneChangedToNull() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // change many-to-one in nested entity to null. - item1_1.setCategory( null ); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the many-to-one from the top level item will win. - assertEquals( category.getName(), item1Merged.getCategory().getName() ); - assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( category.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testNestedManyToOneChangedToNewEntity() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // change many-to-one in nested entity to a new (transient) value - Category categoryNew = new Category(); - categoryNew.setName( "new category" ); - item1_1.setCategory( categoryNew ); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the many-to-one from the top level item will win. - assertEquals( category.getName(), item1Merged.getCategory().getName() ); - assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( category.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - // make sure new category got persisted - Category categoryQueried = (Category) s.createQuery( "from Category c where c.name='new category'" ).uniqueResult(); - assertNotNull( categoryQueried ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testTopLevelManyToOneChangedToNewEntity() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // change many-to-one in top level to be a new (transient) - Category categoryNewer = new Category(); - categoryNewer.setName( "newer category" ); - item1.setCategory( categoryNewer ); - - // put the other representation in categoryNewer - categoryNewer.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the many-to-one from the top level item will win. - assertEquals( categoryNewer.getName(), item1Merged.getCategory().getName() ); - assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( categoryNewer.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - // make sure original category is still there - Category categoryQueried = (Category) s.createQuery( "from Category c where c.name='category'" ).uniqueResult(); - assertNotNull( categoryQueried ); - // make sure original category has the same item. - assertSame( item1, categoryQueried.getExampleItem() ); - // set exampleItem to null to avoid constraint violation on cleanup. - categoryQueried.setExampleItem( null ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testTopLevelManyToOneManagedNestedIsDetached() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - - item1Merged.setCategory( category ); - category.setExampleItem( item1_1 ); - - // now item1Merged is managed and it has a nested detached item - s.merge( item1Merged ); - assertEquals( category.getName(), item1Merged.getCategory().getName() ); - assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( category.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testNestedValueCollectionWithChangedElements() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.getColors().add( "red" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getColors() ); - tx.commit(); - s.close(); - - // add an element to collection in nested entity - item1_1.getColors().add( "blue" ); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the collection from the top level item will win. - assertEquals( 1, item1Merged.getColors().size() ); - assertEquals( "red", item1Merged.getColors().iterator().next() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getColors().size() ); - assertEquals( "red", item1.getColors().iterator().next() ); - Hibernate.initialize( item1.getCategory() ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getColors() ); - tx.commit(); - s.close(); - - // remove the existing elements from collection in nested entity - item1_1.getColors().clear(); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - item1Merged = (Item) s.merge( item1 ); - // the collection from the top level item will win. - assertEquals( 1, item1Merged.getColors().size() ); - assertEquals( "red", item1Merged.getColors().iterator().next() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getColors().size() ); - assertEquals( "red", item1.getColors().iterator().next() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testTopValueCollectionWithChangedElements() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.getColors().add( "red" ); - - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // add an element to collection in nested entity - item1.getColors().add( "blue" ); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // the collection from the top level item will win. - assertEquals( 2, item1Merged.getColors().size() ); - assertTrue( item1Merged.getColors().contains( "red" ) ); - assertTrue( item1Merged.getColors().contains( "blue" ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 2, item1.getColors().size() ); - assertTrue( item1.getColors().contains( "red" ) ); - assertTrue( item1.getColors().contains( "blue" ) ); - Hibernate.initialize( item1.getCategory() ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - // remove the existing elements from collection in nested entity - item1.getColors().clear(); - item1.getCategory().setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - item1Merged = (Item) s.merge( item1 ); - // the collection from the top level item will win. - assertTrue( item1Merged.getColors().isEmpty() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertTrue( item1.getColors().isEmpty() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testCascadeFromTransientToNonDirtyRepresentations() { - - Item item1 = new Item(); - item1.setName( "item1" ); - - Session s = openSession(); - Transaction tx = session.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // Get another representation of the same Item from a different session. - - s = openSession(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Create a transient entity that references both representations. - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testCascadeFromDetachedToNonDirtyRepresentations() { - Item item1 = new Item(); - item1.setName( "item1" ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - Session s = openSession(); - Transaction tx = session.beginTransaction(); - s.persist( item1 ); - s.persist( hoarder ); - tx.commit(); - s.close(); - - // Get another representation of the same Item from a different session. - - s = openSession(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Update hoarder (detached) to references both representations. - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testCascadeFromDetachedToGT2DirtyRepresentations() { - Item item1 = new Item(); - item1.setName( "item1" ); - Category category1 = new Category(); - category1.setName( "category1" ); - item1.setCategory( category1 ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - Session s = openSession(); - Transaction tx = session.beginTransaction(); - s.persist( item1 ); - s.persist( hoarder ); - tx.commit(); - s.close(); - - // Get another representation of the same Item from a different session. - - s = openSession(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1 and item1_1 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Get another representation of the same Item from a different session. - - s = openSession(); - Item item1_2 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_2 ); - assertTrue( item1.equals( item1_2) ); - - item1_1.setName( "item1_1" ); - item1_2.setName( "item1_2" ); - - // Update hoarder (detached) to references both representations. - item1.getCategory().setExampleItem( item1_2 ); - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - hoarder.getFavoriteItem().getCategory(); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getFavoriteItem().getCategory().getExampleItem() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - assertEquals( item1.getName(), hoarder.getFavoriteItem().getName() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getFavoriteItem().getCategory().getExampleItem() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testTopLevelEntityNewerThanNested() { - Item item = new Item(); - item.setName( "item" ); - - Category category = new Category(); - category.setName( "category" ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item ); - s.persist( category ); - tx.commit(); - s.close(); - - // Get the Category from a different session. - s = openSession(); - tx = s.beginTransaction(); - Category category1_2 = (Category) s.get( Category.class, category.getId() ); - tx.commit(); - s.close(); - - // Get and update the same Category. - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category.getId() ); - category1_1.setName( "new name" ); - tx.commit(); - s.close(); - - assertTrue( category1_2.getVersion() < category1_1.getVersion() ); - - category1_1.setExampleItem( item ); - item.setCategory( category1_2 ); - - s = openSession(); - tx = s.beginTransaction(); - try { - // representation merged at top level is newer than nested representation. - category1_1 = (Category) s.merge( category1_1 ); - fail( "should have failed because one representation is an older version." ); - } - catch (PersistenceException e){ - // expected - assertTyping( StaleObjectStateException.class, e.getCause()); - } - finally { - tx.rollback(); - s.close(); - } - - cleanup(); - } - - @Test - public void testNestedEntityNewerThanTopLevel() { - Item item = new Item(); - item.setName( "item" ); - - Category category = new Category(); - category.setName( "category" ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item ); - s.persist( category ); - tx.commit(); - s.close(); - - // Get category1_1 from a different session. - s = openSession(); - Category category1_1 = (Category) s.get( Category.class, category.getId() ); - s.close(); - - // Get and update category1_2 to increment its version. - s = openSession(); - tx = s.beginTransaction(); - Category category1_2 = (Category) s.get( Category.class, category.getId() ); - category1_2.setName( "new name" ); - tx.commit(); - s.close(); - - assertTrue( category1_2.getVersion() > category1_1.getVersion() ); - - category1_1.setExampleItem( item ); - item.setCategory( category1_2 ); - - s = openSession(); - tx = s.beginTransaction(); - try { - // nested representation is newer than top lever representation. - category1_1 = (Category) s.merge( category1_1 ); - fail( "should have failed because one representation is an older version." ); - } - catch (PersistenceException e){ - // expected - assertTyping( StaleObjectStateException.class, e.getCause()); - } - finally { - tx.rollback(); - s.close(); - } - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9240" ) - public void testTopLevelUnidirOneToManyBackrefWithNewElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); - - Category category = new Category(); - category.setName( "category" ); - - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - // The following will fail due to PropertyValueException because item1 will - // be removed from the inverted merge map when the operation cascades to item1_1. - Item item1Merged = (Item) s.merge( item1 ); - // top-level collection should win - assertEquals( 2, item1.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 2, item1.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyBackrefWithNewElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getSubItemsBackref() ); - tx.commit(); - s.close(); - - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1_1.getSubItemsBackref().add( subItem2 ); - - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // The resulting collection should contain the added element - assertEquals( 2, item1Merged.getSubItemsBackref().size() ); - assertEquals( "subItem1 name", item1Merged.getSubItemsBackref().get( 0 ).getName() ); - assertEquals( "subItem2 name", item1Merged.getSubItemsBackref().get( 1 ).getName() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 2, item1.getSubItemsBackref().size() ); - assertEquals( "subItem1 name", item1.getSubItemsBackref().get( 0 ).getName() ); - assertEquals( "subItem2 name", item1Merged.getSubItemsBackref().get( 1 ).getName() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyBackrefWithRemovedElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( item1_1.getSubItemsBackref() ) ); - - Category category = new Category(); - category.setName( "category" ); - - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - // remove subItem1 from top-level Item - item1.getSubItemsBackref().remove( subItem1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // entity should have been removed - assertEquals( 1, item1Merged.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getSubItemsBackref().size() ); - subItem1 = (SubItem) s.get( SubItem.class, subItem1.getId() ); - // cascade does not include delete-orphan, so subItem1 should still be persistent. - assertNotNull( subItem1 ); - tx.commit(); - - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyBackrefWithRemovedElement() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - SubItem subItem1 = new SubItem(); - subItem1.setName( "subItem1 name" ); - item1.getSubItemsBackref().add( subItem1 ); - SubItem subItem2 = new SubItem(); - subItem2.setName( "subItem2 name" ); - item1.getSubItemsBackref().add( subItem2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - Hibernate.initialize( item1_1.getSubItemsBackref() ); - tx.commit(); - s.close(); - - // remove subItem1 from the nested Item - item1_1.getSubItemsBackref().remove( subItem1 ); - - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - // entity should have been removed - assertEquals( 1, item1Merged.getSubItemsBackref().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( 1, item1.getSubItemsBackref().size() ); - subItem1 = (SubItem) s.get( SubItem.class, subItem1.getId() ); - // cascade does not include delete-orphan, so subItem1 should still be persistent. - assertNotNull( subItem1 ); - tx.commit(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyNoBackrefWithNewElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); - - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 2, category1Merged.getSubCategories().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 2, category1.getSubCategories().size() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyNoBackrefWithNewElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - Hibernate.initialize( category1_1.getSubCategories() ); - tx.commit(); - s.close(); - - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1_1.getSubCategories().add( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 2, category1Merged.getSubCategories().size() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 2, category1.getSubCategories().size() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - //@FailureExpected( jiraKey = "HHH-9106" ) - public void testTopLevelUnidirOneToManyNoBackrefWithRemovedElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - tx.commit(); - s.close(); - - assertFalse( Hibernate.isInitialized( category1_1.getSubCategories() ) ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - category1.getSubCategories().remove( subCategory1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 1, category1Merged.getSubCategories().size() ); - assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 1, category1.getSubCategories().size() ); - assertTrue( category1.getSubCategories().contains( subCategory2 ) ); - // cascade does not include delete-orphan, so subCategory1 should still be persistent. - subCategory1 = (SubCategory) s.get( SubCategory.class, subCategory1.getId() ); - assertNotNull( subCategory1 ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - @FailureExpected( jiraKey = "HHH-9239" ) - public void testNestedUnidirOneToManyNoBackrefWithRemovedElement() { - Category category1 = new Category(); - category1.setName( "category1 name" ); - SubCategory subCategory1 = new SubCategory(); - subCategory1.setName( "subCategory1 name" ); - category1.getSubCategories().add( subCategory1 ); - SubCategory subCategory2 = new SubCategory(); - subCategory2.setName( "subCategory2 name" ); - category1.getSubCategories().add( subCategory2 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( category1 ); - tx.commit(); - s.close(); - - // get another representation of category1 - s = openSession(); - tx = s.beginTransaction(); - Category category1_1 = (Category) s.get( Category.class, category1.getId() ); - Hibernate.initialize( category1_1.getSubCategories() ); - tx.commit(); - s.close(); - - category1_1.getSubCategories().remove( subCategory2 ); - - Item item = new Item(); - item.setName( "item" ); - category1.setExampleItem( item ); - item.setCategory( category1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - Category category1Merged = (Category) s.merge( category1 ); - assertEquals( 1, category1Merged.getSubCategories().size() ); - assertTrue( category1Merged.getSubCategories().contains( subCategory2 ) ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - category1 = (Category) s.get( Category.class, category1.getId() ); - assertEquals( 1, category1.getSubCategories().size() ); - assertTrue( category1.getSubCategories().contains( subCategory2 ) ); - // cascade does not include delete-orphan, so subCategory1 should still be persistent. - subCategory1 = (SubCategory) s.get( SubCategory.class, subCategory1.getId() ); - assertNotNull( subCategory1 ); - tx.commit(); - s.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - Session s = openSession(); - s.beginTransaction(); - - s.createQuery( "delete from SubItem" ).executeUpdate(); - for ( Hoarder hoarder : (List) s.createQuery( "from Hoarder" ).list() ) { - hoarder.getItems().clear(); - s.delete( hoarder ); - } - - for ( Category category : (List) s.createQuery( "from Category" ).list() ) { - Item exampleItem = category.getExampleItem(); - if ( exampleItem != null ) { - category.setExampleItem( null ); - exampleItem.setCategory( null ); - s.delete( category ); - s.delete (exampleItem ); - } - } - - for ( Item item : (List) s.createQuery( "from Item" ).list() ) { - Category category = item.getCategory(); - item.setCategory( null ); - if ( category != null ) { - category.setExampleItem( null ); - } - s.delete( item ); - } - - s.createQuery( "delete from Item" ).executeUpdate(); - - - s.getTransaction().commit(); - s.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesCustomTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesCustomTest.java deleted file mode 100644 index b53252882b..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesCustomTest.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import java.util.List; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.cfg.Configuration; -import org.hibernate.event.spi.EntityCopyObserver; -import org.hibernate.event.spi.EventSource; - -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * Tests merging multiple detached representations of the same entity using a custom EntityCopyObserver. - * - * @author Gail Badner - */ -@TestForIssue( jiraKey = "HHH-9106") -public class MergeMultipleEntityCopiesCustomTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[] { - "ops/Hoarder.hbm.xml" - }; - } - - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( - "hibernate.event.merge.entity_copy_observer", - CustomEntityCopyObserver.class.getName() - ); - } - - @Test - public void testMergeMultipleEntityCopiesAllowed() { - Item item1 = new Item(); - item1.setName( "item1" ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - Session s = openSession(); - s.getTransaction().begin(); - s.persist( item1 ); - s.persist( hoarder ); - s.getTransaction().commit(); - s.close(); - - // Get another representation of the same Item. - - s = openSession(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Update hoarder (detached) to references both representations. - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - s = openSession(); - s.getTransaction().begin(); - // the merge should succeed because it does not have Category copies. - // (CustomEntityCopyObserver does not allow Category copies; it does allow Item copies) - hoarder = (Hoarder) s.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.getTransaction().begin(); - hoarder = (Hoarder) s.get( Hoarder.class, hoarder.getId() ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - s.getTransaction().commit(); - s.close(); - - cleanup(); - } - - @Test - public void testMergeMultipleEntityCopiesAllowedAndDisallowed() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - s.getTransaction().begin(); - s.persist( item1 ); - s.getTransaction().commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - s.getTransaction().begin(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - // make sure item1_1.category is initialized - Hibernate.initialize( item1_1.getCategory() ); - s.getTransaction().commit(); - s.close(); - - s = openSession(); - s.getTransaction().begin(); - Item item1Merged = (Item) s.merge( item1 ); - - item1Merged.setCategory( category ); - category.setExampleItem( item1_1 ); - - // now item1Merged is managed and it has a nested detached item - // and there is multiple managed/detached Category objects - try { - // the following should fail because multiple copies of Category objects is not allowed by - // CustomEntityCopyObserver - s.merge( item1Merged ); - fail( "should have failed because CustomEntityCopyObserver does not allow multiple copies of a Category. "); - } - catch (IllegalStateException ex ) { - // expected - } - finally { - s.getTransaction().rollback(); - } - s.close(); - - s = openSession(); - s.getTransaction().begin(); - item1 = (Item) s.get( Item.class, item1.getId() ); - assertEquals( category.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - s.getTransaction().commit(); - s.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - Session s = openSession(); - s.getTransaction().begin(); - - for ( Hoarder hoarder : (List) s.createQuery( "from Hoarder" ).list() ) { - hoarder.getItems().clear(); - s.delete( hoarder ); - } - - for ( Category category : (List) s.createQuery( "from Category" ).list() ) { - if ( category.getExampleItem() != null ) { - category.setExampleItem( null ); - s.delete( category ); - } - } - - for ( Item item : (List) s.createQuery( "from Item" ).list() ) { - item.setCategory( null ); - s.delete( item ); - } - - s.createQuery( "delete from Item" ).executeUpdate(); - - s.getTransaction().commit(); - s.close(); - } - - @Override - public Class[] getAnnotatedClasses() { - return new Class[] { - Category.class, - Hoarder.class, - Item.class - }; - } - - public static class CustomEntityCopyObserver implements EntityCopyObserver { - - @Override - public void entityCopyDetected(Object managedEntity, Object mergeEntity1, Object mergeEntity2, EventSource session) { - if ( Category.class.isInstance( managedEntity ) ) { - throw new IllegalStateException( - String.format( "Entity copies of type [%s] not allowed", Category.class.getName() ) - ); - } - } - - @Override - public void topLevelMergeComplete(EventSource session) { - } - - @Override - public void clear() { - } - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java deleted file mode 100644 index 4a9669a5d1..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import java.util.List; - -import org.junit.Test; - -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Tests merging multiple detached representations of the same entity using - * a the default (that does not allow this). - * - * @author Gail Badner - */ -@TestForIssue( jiraKey = "HHH-9106") -public class MergeMultipleEntityCopiesDisallowedByDefaultTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[] { - "ops/Hoarder.hbm.xml" - }; - } - - @Test - public void testCascadeFromDetachedToNonDirtyRepresentations() { - Item item1 = new Item(); - item1.setName( "item1" ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - Session s = openSession(); - Transaction tx = session.beginTransaction(); - s.persist( item1 ); - s.persist( hoarder ); - tx.commit(); - s.close(); - - // Get another representation of the same Item from a different session. - - s = openSession(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - s.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Update hoarder (detached) to references both representations. - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - s = openSession(); - tx = s.beginTransaction(); - try { - hoarder = (Hoarder) s.merge( hoarder ); - fail( "should have failed due IllegalStateException"); - } - catch (IllegalStateException ex) { - //expected - } - finally { - tx.rollback(); - s.close(); - } - - cleanup(); - } - - @Test - public void testTopLevelManyToOneManagedNestedIsDetached() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1 ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - s.persist( item1 ); - tx.commit(); - s.close(); - - // get another representation of item1 - s = openSession(); - tx = s.beginTransaction(); - Item item1_1 = (Item) s.get( Item.class, item1.getId() ); - tx.commit(); - s.close(); - - s = openSession(); - tx = s.beginTransaction(); - Item item1Merged = (Item) s.merge( item1 ); - - item1Merged.setCategory( category ); - category.setExampleItem( item1_1 ); - - // now item1Merged is managed and it has a nested detached item - try { - s.merge( item1Merged ); - fail( "should have failed due IllegalStateException"); - } - catch (IllegalStateException ex) { - //expected - } - finally { - tx.rollback(); - s.close(); - } - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - Session s = openSession(); - s.beginTransaction(); - - s.createQuery( "delete from SubItem" ).executeUpdate(); - for ( Hoarder hoarder : (List) s.createQuery( "from Hoarder" ).list() ) { - hoarder.getItems().clear(); - s.delete( hoarder ); - } - - for ( Category category : (List) s.createQuery( "from Category" ).list() ) { - if ( category.getExampleItem() != null ) { - category.setExampleItem( null ); - s.delete( category ); - } - } - - for ( Item item : (List) s.createQuery( "from Item" ).list() ) { - item.setCategory( null ); - s.delete( item ); - } - - s.createQuery( "delete from Item" ).executeUpdate(); - - s.getTransaction().commit(); - s.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java deleted file mode 100755 index d74c4e16c5..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/MergeTest.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import javax.persistence.PersistenceException; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.junit.Test; - -import org.hibernate.Hibernate; -import org.hibernate.NonUniqueObjectException; -import org.hibernate.Session; -import org.hibernate.StaleObjectStateException; -import org.hibernate.Transaction; -import org.hibernate.dialect.AbstractHANADialect; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.SkipForDialect; - -import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Gavin King - */ -@RequiresDialectFeature(DialectChecks.SupportsNoColumnInsert.class) -public class MergeTest extends AbstractOperationTestCase { - @Test - public void testMergeStaleVersionFails() throws Exception { - Session s = openSession(); - s.beginTransaction(); - VersionedEntity entity = new VersionedEntity( "entity", "entity" ); - s.persist( entity ); - s.getTransaction().commit(); - s.close(); - - // make the detached 'entity' reference stale... - s = openSession(); - s.beginTransaction(); - VersionedEntity entity2 = ( VersionedEntity ) s.get( VersionedEntity.class, entity.getId() ); - entity2.setName( "entity-name" ); - s.getTransaction().commit(); - s.close(); - - // now try to reattch it - s = openSession(); - s.beginTransaction(); - try { - s.merge( entity ); - s.getTransaction().commit(); - fail( "was expecting staleness error" ); - } - catch (PersistenceException e){ - // expected - assertTyping( StaleObjectStateException.class, e.getCause()); - } - finally { - s.getTransaction().rollback(); - s.close(); - } - } - - @Test - public void testMergeBidiPrimayKeyOneToOne() throws Exception { - rebuildSessionFactory(); - Session s = openSession(); - s.beginTransaction(); - Person p = new Person( "steve" ); - new PersonalDetails( "I have big feet", p ); - s.persist( p ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - p.getDetails().setSomePersonalDetail( p.getDetails().getSomePersonalDetail() + " and big hands too" ); - s = openSession(); - s.beginTransaction(); - p = ( Person ) s.merge( p ); - s.getTransaction().commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 1 ); - assertDeleteCount( 0 ); - - s = openSession(); - s.beginTransaction(); - s.delete( p ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testMergeBidiForeignKeyOneToOne() throws Exception { - Session s = openSession(); - s.beginTransaction(); - Person p = new Person( "steve" ); - Address a = new Address( "123 Main", "Austin", "US", p ); - s.persist( a ); - s.persist( p ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - p.getAddress().setStreetAddress( "321 Main" ); - s = openSession(); - s.beginTransaction(); - p = ( Person ) s.merge( p ); - s.getTransaction().commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); // no cascade - assertDeleteCount( 0 ); - - s = openSession(); - s.beginTransaction(); - s.delete( a ); - s.delete( p ); - s.getTransaction().commit(); - s.close(); - } - - @Test - @SuppressWarnings( {"UnusedAssignment"}) - public void testNoExtraUpdatesOnMerge() throws Exception { - Session s = openSession(); - s.beginTransaction(); - Node node = new Node( "test" ); - s.persist( node ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - // node is now detached, but we have made no changes. so attempt to merge it - // into this new session; this should cause no updates... - s = openSession(); - s.beginTransaction(); - node = ( Node ) s.merge( node ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - - /////////////////////////////////////////////////////////////////////// - // as a control measure, now update the node while it is detached and - // make sure we get an update as a result... - node.setDescription( "new description" ); - s = openSession(); - s.beginTransaction(); - node = ( Node ) s.merge( node ); - s.getTransaction().commit(); - s.close(); - assertUpdateCount( 1 ); - assertInsertCount( 0 ); - /////////////////////////////////////////////////////////////////////// - - cleanup(); - } - - @Test - @SuppressWarnings( {"unchecked", "UnusedAssignment"}) - public void testNoExtraUpdatesOnMergeWithCollection() throws Exception { - Session s = openSession(); - s.beginTransaction(); - Node parent = new Node( "parent" ); - Node child = new Node( "child" ); - parent.getChildren().add( child ); - child.setParent( parent ); - s.persist( parent ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - // parent is now detached, but we have made no changes. so attempt to merge it - // into this new session; this should cause no updates... - s = openSession(); - s.beginTransaction(); - parent = ( Node ) s.merge( parent ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - - /////////////////////////////////////////////////////////////////////// - // as a control measure, now update the node while it is detached and - // make sure we get an update as a result... - ( ( Node ) parent.getChildren().iterator().next() ).setDescription( "child's new description" ); - parent.addChild( new Node( "second child" ) ); - s = openSession(); - s.beginTransaction(); - parent = ( Node ) s.merge( parent ); - s.getTransaction().commit(); - s.close(); - assertUpdateCount( 1 ); - assertInsertCount( 1 ); - /////////////////////////////////////////////////////////////////////// - - cleanup(); - } - - @Test - @SuppressWarnings( {"UnusedAssignment"}) - public void testNoExtraUpdatesOnMergeVersioned() throws Exception { - Session s = openSession(); - s.beginTransaction(); - VersionedEntity entity = new VersionedEntity( "entity", "entity" ); - s.persist( entity ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - // entity is now detached, but we have made no changes. so attempt to merge it - // into this new session; this should cause no updates... - s = openSession(); - s.beginTransaction(); - VersionedEntity mergedEntity = ( VersionedEntity ) s.merge( entity ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - assertEquals( "unexpected version increment", entity.getVersion(), mergedEntity.getVersion() ); - - - /////////////////////////////////////////////////////////////////////// - // as a control measure, now update the node while it is detached and - // make sure we get an update as a result... - entity.setName( "new name" ); - s = openSession(); - s.beginTransaction(); - entity = ( VersionedEntity ) s.merge( entity ); - s.getTransaction().commit(); - s.close(); - assertUpdateCount( 1 ); - assertInsertCount( 0 ); - /////////////////////////////////////////////////////////////////////// - - cleanup(); - } - - @Test - @SuppressWarnings( {"unchecked", "UnusedAssignment"}) - public void testNoExtraUpdatesOnMergeVersionedWithCollection() throws Exception { - Session s = openSession(); - s.beginTransaction(); - VersionedEntity parent = new VersionedEntity( "parent", "parent" ); - VersionedEntity child = new VersionedEntity( "child", "child" ); - parent.getChildren().add( child ); - child.setParent( parent ); - s.persist( parent ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - // parent is now detached, but we have made no changes. so attempt to merge it - // into this new session; this should cause no updates... - s = openSession(); - s.beginTransaction(); - VersionedEntity mergedParent = ( VersionedEntity ) s.merge( parent ); - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - assertEquals( "unexpected parent version increment", parent.getVersion(), mergedParent.getVersion() ); - VersionedEntity mergedChild = ( VersionedEntity ) mergedParent.getChildren().iterator().next(); - assertEquals( "unexpected child version increment", child.getVersion(), mergedChild.getVersion() ); - - /////////////////////////////////////////////////////////////////////// - // as a control measure, now update the node while it is detached and - // make sure we get an update as a result... - mergedParent.setName( "new name" ); - mergedParent.getChildren().add( new VersionedEntity( "child2", "new child" ) ); - s = openSession(); - s.beginTransaction(); - parent = ( VersionedEntity ) s.merge( mergedParent ); - s.getTransaction().commit(); - s.close(); - assertUpdateCount( 1 ); - assertInsertCount( 1 ); - /////////////////////////////////////////////////////////////////////// - - cleanup(); - } - - @Test - @SuppressWarnings( {"unchecked", "UnusedAssignment", "UnusedDeclaration"}) - public void testNoExtraUpdatesOnPersistentMergeVersionedWithCollection() throws Exception { - Session s = openSession(); - s.beginTransaction(); - VersionedEntity parent = new VersionedEntity( "parent", "parent" ); - VersionedEntity child = new VersionedEntity( "child", "child" ); - parent.getChildren().add( child ); - child.setParent( parent ); - s.persist( parent ); - s.getTransaction().commit(); - s.close(); - - clearCounts(); - - // parent is now detached, but we have made no changes. so attempt to merge it - // into this new session; this should cause no updates... - s = openSession(); - s.beginTransaction(); - // load parent so that merge will follow entityIsPersistent path - VersionedEntity persistentParent = ( VersionedEntity ) s.get( VersionedEntity.class, parent.getId() ); - // load children - VersionedEntity persistentChild = ( VersionedEntity ) persistentParent.getChildren().iterator().next(); - VersionedEntity mergedParent = ( VersionedEntity ) s.merge( persistentParent ); // <-- This merge leads to failure - s.getTransaction().commit(); - s.close(); - - assertUpdateCount( 0 ); - assertInsertCount( 0 ); - assertEquals( "unexpected parent version increment", parent.getVersion(), mergedParent.getVersion() ); - VersionedEntity mergedChild = ( VersionedEntity ) mergedParent.getChildren().iterator().next(); - assertEquals( "unexpected child version increment", child.getVersion(), mergedChild.getVersion() ); - - /////////////////////////////////////////////////////////////////////// - // as a control measure, now update the node once it is loaded and - // make sure we get an update as a result... - s = openSession(); - s.beginTransaction(); - persistentParent = ( VersionedEntity ) s.get( VersionedEntity.class, parent.getId() ); - persistentParent.setName( "new name" ); - persistentParent.getChildren().add( new VersionedEntity( "child2", "new child" ) ); - persistentParent = ( VersionedEntity ) s.merge( persistentParent ); - s.getTransaction().commit(); - s.close(); - assertUpdateCount( 1 ); - assertInsertCount( 1 ); - /////////////////////////////////////////////////////////////////////// - - // cleanup(); - } - - @Test - public void testPersistThenMergeInSameTxnWithVersion() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - VersionedEntity entity = new VersionedEntity( "test", "test" ); - s.persist( entity ); - s.merge( new VersionedEntity( "test", "test-2" ) ); - - try { - // control operation... - s.saveOrUpdate( new VersionedEntity( "test", "test-3" ) ); - fail( "saveOrUpdate() should fail here" ); - } - catch( NonUniqueObjectException expected ) { - // expected behavior - } - - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testPersistThenMergeInSameTxnWithTimestamp() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - TimestampedEntity entity = new TimestampedEntity( "test", "test" ); - s.persist( entity ); - s.merge( new TimestampedEntity( "test", "test-2" ) ); - - try { - // control operation... - s.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) ); - fail( "saveOrUpdate() should fail here" ); - } - catch( NonUniqueObjectException expected ) { - // expected behavior - } - - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testMergeDeepTree() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node("root"); - Node child = new Node("child"); - Node grandchild = new Node("grandchild"); - root.addChild(child); - child.addChild(grandchild); - s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(3); - assertUpdateCount(0); - clearCounts(); - - grandchild.setDescription("the grand child"); - Node grandchild2 = new Node("grandchild2"); - child.addChild( grandchild2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(1); - assertUpdateCount(1); - clearCounts(); - - Node child2 = new Node("child2"); - Node grandchild3 = new Node("grandchild3"); - child2.addChild( grandchild3 ); - root.addChild(child2); - - s = openSession(); - tx = s.beginTransaction(); - s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(2); - assertUpdateCount(0); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.delete(grandchild); - s.delete(grandchild2); - s.delete(grandchild3); - s.delete(child); - s.delete(child2); - s.delete(root); - tx.commit(); - s.close(); - - } - - @SuppressWarnings( {"UnusedAssignment"}) - @Test - public void testMergeDeepTreeWithGeneratedId() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode("root"); - NumberedNode child = new NumberedNode("child"); - NumberedNode grandchild = new NumberedNode("grandchild"); - root.addChild(child); - child.addChild(grandchild); - root = (NumberedNode) s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(3); - assertUpdateCount(0); - clearCounts(); - - child = (NumberedNode) root.getChildren().iterator().next(); - grandchild = (NumberedNode) child.getChildren().iterator().next(); - grandchild.setDescription( "the grand child" ); - NumberedNode grandchild2 = new NumberedNode("grandchild2"); - child.addChild( grandchild2 ); - - s = openSession(); - tx = s.beginTransaction(); - root = (NumberedNode) s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount(1); - clearCounts(); - - sessionFactory().getCache().evictEntityRegion( NumberedNode.class ); - - NumberedNode child2 = new NumberedNode("child2"); - NumberedNode grandchild3 = new NumberedNode("grandchild3"); - child2.addChild( grandchild3 ); - root.addChild( child2 ); - - s = openSession(); - tx = s.beginTransaction(); - root = (NumberedNode) s.merge( root ); - tx.commit(); - s.close(); - - assertInsertCount(2); - assertUpdateCount(0); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.createQuery("delete from NumberedNode where name like 'grand%'").executeUpdate(); - s.createQuery("delete from NumberedNode where name like 'child%'").executeUpdate(); - s.createQuery("delete from NumberedNode").executeUpdate(); - tx.commit(); - s.close(); - } - - @Test - public void testMergeTree() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node("root"); - Node child = new Node("child"); - root.addChild(child); - s.persist(root); - tx.commit(); - s.close(); - - assertInsertCount(2); - clearCounts(); - - root.setDescription("The root node"); - child.setDescription("The child node"); - - Node secondChild = new Node("second child"); - - root.addChild(secondChild); - - s = openSession(); - tx = s.beginTransaction(); - s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(1); - assertUpdateCount(2); - - cleanup(); - } - - @Test - public void testMergeTreeWithGeneratedId() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode("root"); - NumberedNode child = new NumberedNode("child"); - root.addChild(child); - s.persist(root); - tx.commit(); - s.close(); - - assertInsertCount(2); - clearCounts(); - - root.setDescription("The root node"); - child.setDescription("The child node"); - - NumberedNode secondChild = new NumberedNode("second child"); - - root.addChild(secondChild); - - s = openSession(); - tx = s.beginTransaction(); - s.merge(root); - tx.commit(); - s.close(); - - assertInsertCount(1); - assertUpdateCount(2); - - cleanup(); - } - - @Test - public void testMergeManaged() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode("root"); - s.persist(root); - tx.commit(); - - clearCounts(); - - tx = s.beginTransaction(); - NumberedNode child = new NumberedNode("child"); - root.addChild( child ); - assertSame( root, s.merge( root ) ); - Object mergedChild = root.getChildren().iterator().next(); - assertNotSame( mergedChild, child ); - assertTrue( s.contains( mergedChild ) ); - assertFalse( s.contains(child) ); - assertEquals( root.getChildren().size(), 1 ); - assertTrue( root.getChildren().contains(mergedChild) ); - //assertNotSame( mergedChild, s.merge(child) ); //yucky :( - tx.commit(); - - assertInsertCount( 1 ); - assertUpdateCount( 0 ); - - assertEquals( root.getChildren().size(), 1 ); - assertTrue( root.getChildren().contains(mergedChild) ); - - s.beginTransaction(); - assertEquals( - Long.valueOf( 2 ), - getNumneredNodeRowCount( s ) - ); - s.getTransaction().commit(); - s.close(); - - cleanup(); - } - - private Long getNumneredNodeRowCount(Session s ){ - CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); - CriteriaQuery criteria = criteriaBuilder.createQuery( Long.class ); - Root root = criteria.from( NumberedNode.class ); - criteria.select( criteriaBuilder.count( root ) ); - return s.createQuery( criteria ).uniqueResult(); - } - - @Test - public void testMergeManagedUninitializedCollection() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - root.addChild( new NumberedNode( "child" ) ); - s.persist( root ); - tx.commit(); - s.close(); - - clearCounts(); - - NumberedNode newRoot = new NumberedNode( "root" ); - newRoot.setId( root.getId() ); - - s = openSession(); - tx = s.beginTransaction(); - root = ( NumberedNode ) s.get( NumberedNode.class, root.getId() ); - Set managedChildren = root.getChildren(); - assertFalse( Hibernate.isInitialized( managedChildren ) ); - newRoot.setChildren( managedChildren ); - assertSame( root, s.merge( newRoot ) ); - assertSame( managedChildren, root.getChildren() ); - assertFalse( Hibernate.isInitialized( managedChildren ) ); - tx.commit(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - assertDeleteCount( 0 ); - - tx = s.beginTransaction(); - assertEquals( - Long.valueOf( 2 ), - getNumneredNodeRowCount( s ) - ); - tx.commit(); - - s.close(); - - cleanup(); - } - - @Test - public void testMergeManagedInitializedCollection() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - root.addChild( new NumberedNode( "child" ) ); - s.persist(root); - tx.commit(); - s.close(); - - clearCounts(); - - NumberedNode newRoot = new NumberedNode( "root" ); - newRoot.setId( root.getId() ); - - s = openSession(); - tx = s.beginTransaction(); - root = ( NumberedNode ) s.get( NumberedNode.class, root.getId() ); - Set managedChildren = root.getChildren(); - Hibernate.initialize( managedChildren ); - assertTrue( Hibernate.isInitialized( managedChildren ) ); - newRoot.setChildren( managedChildren ); - assertSame( root, s.merge( newRoot ) ); - assertSame( managedChildren, root.getChildren() ); - assertTrue( Hibernate.isInitialized( managedChildren ) ); - tx.commit(); - - assertInsertCount(0); - assertUpdateCount(0); - assertDeleteCount(0); - - tx = s.beginTransaction(); - assertEquals( - Long.valueOf( 2 ), - getNumneredNodeRowCount( s ) - ); - tx.commit(); - - s.close(); - - cleanup(); - } - - @Test - @SuppressWarnings( {"unchecked"}) - @SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column") - public void testRecursiveMergeTransient() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Employer jboss = new Employer(); - Employee gavin = new Employee(); - jboss.setEmployees( new ArrayList() ); - jboss.getEmployees().add( gavin ); - s.merge( jboss ); - s.flush(); - jboss = (Employer) s.createQuery("from Employer e join fetch e.employees").uniqueResult(); - assertTrue( Hibernate.isInitialized( jboss.getEmployees() ) ); - assertEquals( 1, jboss.getEmployees().size() ); - s.clear(); - s.merge( jboss.getEmployees().iterator().next() ); - tx.commit(); - s.close(); - - cleanup(); - } - - @Test - public void testDeleteAndMerge() { - Session s = openSession(); - s.getTransaction().begin(); - Employer jboss = new Employer(); - s.persist( jboss ); - s.getTransaction().commit(); - s.clear(); - - s.getTransaction().begin(); - Employer otherJboss; - otherJboss = s.get( Employer.class, jboss.getId() ); - s.delete( otherJboss ); - s.getTransaction().commit(); - s.clear(); - jboss.setVers( Integer.valueOf( 1 ) ); - s.getTransaction().begin(); - s.merge( jboss ); - s.getTransaction().commit(); - s.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - @Test - @SkipForDialect(value = AbstractHANADialect.class, comment = " HANA doesn't support tables consisting of only a single auto-generated column") - public void testMergeManyToManyWithCollectionDeference() { - // setup base data... - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Competition competition = new Competition(); - competition.getCompetitors().add( new Competitor( "Name" ) ); - competition.getCompetitors().add( new Competitor() ); - competition.getCompetitors().add( new Competitor() ); - s.persist( competition ); - tx.commit(); - s.close(); - - // the competition graph is now detached: - // 1) create a new List reference to represent the competitors - s = openSession(); - tx = s.beginTransaction(); - List newComp = new ArrayList(); - Competitor originalCompetitor = ( Competitor ) competition.getCompetitors().get( 0 ); - originalCompetitor.setName( "Name2" ); - newComp.add( originalCompetitor ); - newComp.add( new Competitor() ); - // 2) set that new List reference unto the Competition reference - competition.setCompetitors( newComp ); - // 3) attempt the merge - Competition competition2 = ( Competition ) s.merge( competition ); - tx.commit(); - s.close(); - - assertFalse( competition == competition2 ); - assertFalse( competition.getCompetitors() == competition2.getCompetitors() ); - assertEquals( 2, competition2.getCompetitors().size() ); - - s = openSession(); - tx = s.beginTransaction(); - competition = ( Competition ) s.get( Competition.class, competition.getId() ); - assertEquals( 2, competition.getCompetitors().size() ); - s.delete( competition ); - tx.commit(); - s.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - Session s = openSession(); - s.beginTransaction(); - s.createQuery( "delete from NumberedNode where parent is not null" ).executeUpdate(); - s.createQuery( "delete from NumberedNode" ).executeUpdate(); - - s.createQuery( "delete from Node where parent is not null" ).executeUpdate(); - s.createQuery( "delete from Node" ).executeUpdate(); - - s.createQuery( "delete from VersionedEntity where parent is not null" ).executeUpdate(); - s.createQuery( "delete from VersionedEntity" ).executeUpdate(); - s.createQuery( "delete from TimestampedEntity" ).executeUpdate(); - - s.createQuery( "delete from Competitor" ).executeUpdate(); - s.createQuery( "delete from Competition" ).executeUpdate(); - - for ( Employer employer : (List) s.createQuery( "from Employer" ).list() ) { - s.delete( employer ); - } - - s.getTransaction().commit(); - s.close(); - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/OracleNoColumnInsertTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/OracleNoColumnInsertTest.java deleted file mode 100644 index 9d0e4c6816..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/OracleNoColumnInsertTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.hibernate.dialect.Oracle9iDialect; - -import org.hibernate.testing.RequiresDialect; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; - -/** - * @author Vlad Mihalcea - */ -@RequiresDialect(value = { Oracle9iDialect.class }) -@TestForIssue( jiraKey = "HHH-13104" ) -public class OracleNoColumnInsertTest extends BaseCoreFunctionalTestCase { - - public String[] getMappings() { - return new String[] { - "ops/Competition.hbm.xml" - }; - } - - @Test - public void test() throws Exception { - doInHibernate( this::sessionFactory, session -> { - Competition competition = new Competition(); - - session.persist( competition ); - } ); - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java deleted file mode 100755 index a7684cfb52..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SaveOrUpdateTest.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import java.util.Map; - -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; - -import org.hibernate.Hibernate; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.engine.spi.PersistentAttributeInterceptable; - -import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Gavin King - */ -public class SaveOrUpdateTest extends BaseNonConfigCoreFunctionalTestCase { - @Override - protected void addSettings(Map settings) { - settings.put( AvailableSettings.GENERATE_STATISTICS, "true" ); - settings.put( AvailableSettings.STATEMENT_BATCH_SIZE, "0" ); - } - - @Override - public String[] getMappings() { - return new String[] {"ops/Node.hbm.xml"}; - } - - @Override - protected String getCacheConcurrencyStrategy() { - return "nonstrict-read-write"; - } - - @Test - public void testSaveOrUpdateDeepTree() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node( "root" ); - Node child = new Node( "child" ); - Node grandchild = new Node( "grandchild" ); - root.addChild( child ); - child.addChild( grandchild ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 3 ); - assertUpdateCount( 0 ); - clearCounts(); - - grandchild.setDescription( "the grand child" ); - Node grandchild2 = new Node( "grandchild2" ); - child.addChild( grandchild2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 1 ); - clearCounts(); - - Node child2 = new Node( "child2" ); - Node grandchild3 = new Node( "grandchild3" ); - child2.addChild( grandchild3 ); - root.addChild( child2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 2 ); - assertUpdateCount( 0 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.delete( grandchild ); - s.delete( grandchild2 ); - s.delete( grandchild3 ); - s.delete( child ); - s.delete( child2 ); - s.delete( root ); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateDeepTreeWithGeneratedId() { - boolean instrumented = PersistentAttributeInterceptable.class.isAssignableFrom( NumberedNode.class ); - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - NumberedNode child = new NumberedNode( "child" ); - NumberedNode grandchild = new NumberedNode( "grandchild" ); - root.addChild( child ); - child.addChild( grandchild ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 3 ); - assertUpdateCount( 0 ); - clearCounts(); - - child = ( NumberedNode ) root.getChildren().iterator().next(); - grandchild = ( NumberedNode ) child.getChildren().iterator().next(); - grandchild.setDescription( "the grand child" ); - NumberedNode grandchild2 = new NumberedNode( "grandchild2" ); - child.addChild( grandchild2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( instrumented ? 1 : 3 ); - clearCounts(); - - NumberedNode child2 = new NumberedNode( "child2" ); - NumberedNode grandchild3 = new NumberedNode( "grandchild3" ); - child2.addChild( grandchild3 ); - root.addChild( child2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 2 ); - assertUpdateCount( instrumented ? 0 : 4 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.createQuery( "delete from NumberedNode where name like 'grand%'" ).executeUpdate(); - s.createQuery( "delete from NumberedNode where name like 'child%'" ).executeUpdate(); - s.createQuery( "delete from NumberedNode" ).executeUpdate(); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateTree() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node( "root" ); - Node child = new Node( "child" ); - root.addChild( child ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 2 ); - clearCounts(); - - root.setDescription( "The root node" ); - child.setDescription( "The child node" ); - - Node secondChild = new Node( "second child" ); - - root.addChild( secondChild ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.createQuery( "delete from Node where parent is not null" ).executeUpdate(); - s.createQuery( "delete from Node" ).executeUpdate(); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateTreeWithGeneratedId() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - NumberedNode child = new NumberedNode( "child" ); - root.addChild( child ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 2 ); - clearCounts(); - - root.setDescription( "The root node" ); - child.setDescription( "The child node" ); - - NumberedNode secondChild = new NumberedNode( "second child" ); - - root.addChild( secondChild ); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 2 ); - - s = openSession(); - tx = s.beginTransaction(); - s.createQuery( "delete from NumberedNode where parent is not null" ).executeUpdate(); - s.createQuery( "delete from NumberedNode" ).executeUpdate(); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateManaged() { - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - s.saveOrUpdate( root ); - tx.commit(); - - tx = s.beginTransaction(); - NumberedNode child = new NumberedNode( "child" ); - root.addChild( child ); - s.saveOrUpdate( root ); - assertFalse( s.contains( child ) ); - s.flush(); - assertTrue( s.contains( child ) ); - tx.commit(); - - assertTrue( root.getChildren().contains( child ) ); - assertEquals( root.getChildren().size(), 1 ); - - tx = s.beginTransaction(); - assertEquals( - Long.valueOf( 2 ), - getRowCount( s, NumberedNode.class ) - ); - s.delete( root ); - s.delete( child ); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateGot() { - clearCounts(); - - boolean instrumented = PersistentAttributeInterceptable.class.isAssignableFrom( NumberedNode.class ); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 0 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( instrumented ? 0 : 1 ); - - s = openSession(); - tx = s.beginTransaction(); - root = s.get( NumberedNode.class, new Long( root.getId() ) ); - Hibernate.initialize( root.getChildren() ); - tx.commit(); - s.close(); - - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - NumberedNode child = new NumberedNode( "child" ); - root.addChild( child ); - s.saveOrUpdate( root ); - assertTrue( s.contains( child ) ); - tx.commit(); - - assertInsertCount( 1 ); - assertUpdateCount( instrumented ? 0 : 1 ); - - tx = s.beginTransaction(); - assertEquals( - new Long( 2 ), - getRowCount( s, NumberedNode.class ) - ); - s.delete( root ); - s.delete( child ); - tx.commit(); - s.close(); - } - - @Test - public void testSaveOrUpdateGotWithMutableProp() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - Node root = new Node( "root" ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 0 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - - s = openSession(); - tx = s.beginTransaction(); - root = s.get( Node.class, "root" ); - Hibernate.initialize( root.getChildren() ); - tx.commit(); - s.close(); - - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - Node child = new Node( "child" ); - root.addChild( child ); - s.saveOrUpdate( root ); - assertTrue( s.contains( child ) ); - tx.commit(); - - assertInsertCount( 1 ); - assertUpdateCount( 1 ); //note: will fail here if no second-level cache - - tx = s.beginTransaction(); - assertEquals( - new Long( 2 ), - getRowCount(s, Node.class) - ); - s.delete( root ); - s.delete( child ); - tx.commit(); - s.close(); - } - - @Test - public void testEvictThenSaveOrUpdate() { - Session s = openSession(); - s.getTransaction().begin(); - Node parent = new Node( "1:parent" ); - Node child = new Node( "2:child" ); - Node grandchild = new Node( "3:grandchild" ); - parent.addChild( child ); - child.addChild( grandchild ); - s.saveOrUpdate( parent ); - s.getTransaction().commit(); - s.close(); - - Session s1 = openSession(); - s1.getTransaction().begin(); - child = ( Node ) s1.load( Node.class, "2:child" ); - assertTrue( s1.contains( child ) ); - assertFalse( Hibernate.isInitialized( child ) ); - assertTrue( s1.contains( child.getParent() ) ); - assertTrue( Hibernate.isInitialized( child ) ); - assertFalse( Hibernate.isInitialized( child.getChildren() ) ); - assertFalse( Hibernate.isInitialized( child.getParent() ) ); - assertTrue( s1.contains( child ) ); - s1.evict( child ); - assertFalse( s1.contains( child ) ); - assertTrue( s1.contains( child.getParent() ) ); - - Session s2 = openSession(); - try { - s2.getTransaction().begin(); - s2.saveOrUpdate( child ); - fail(); - } - catch ( HibernateException ex ) { - // expected because parent is connected to s1 - } - finally { - s2.getTransaction().rollback(); - } - s2.close(); - - s1.evict( child.getParent() ); - assertFalse( s1.contains( child.getParent() ) ); - - s2 = openSession(); - s2.getTransaction().begin(); - s2.saveOrUpdate( child ); - assertTrue( s2.contains( child ) ); - assertFalse( s1.contains( child ) ); - assertTrue( s2.contains( child.getParent() ) ); - assertFalse( s1.contains( child.getParent() ) ); - assertFalse( Hibernate.isInitialized( child.getChildren() ) ); - assertFalse( Hibernate.isInitialized( child.getParent() ) ); - assertEquals( 1, child.getChildren().size() ); - assertEquals( "1:parent", child.getParent().getName() ); - assertTrue( Hibernate.isInitialized( child.getChildren() ) ); - assertFalse( Hibernate.isInitialized( child.getParent() ) ); - assertNull( child.getParent().getDescription() ); - assertTrue( Hibernate.isInitialized( child.getParent() ) ); - - s1.getTransaction().commit(); - s2.getTransaction().commit(); - s1.close(); - s2.close(); - - s = openSession(); - s.beginTransaction(); - s.delete( s.get( Node.class, "3:grandchild" ) ); - s.delete( s.get( Node.class, "2:child" ) ); - s.delete( s.get( Node.class, "1:parent" ) ); - s.getTransaction().commit(); - s.close(); - } - - @Test - public void testSavePersistentEntityWithUpdate() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - NumberedNode root = new NumberedNode( "root" ); - root.setName( "a name" ); - s.saveOrUpdate( root ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 0 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - root = ( NumberedNode ) s.get( NumberedNode.class, root.getId() ); - assertEquals( "a name", root.getName() ); - root.setName( "a new name" ); - s.save( root ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 1 ); - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - root = ( NumberedNode ) s.get( NumberedNode.class, root.getId() ); - assertEquals( "a new name", root.getName() ); - s.delete( root ); - tx.commit(); - s.close(); - } - - private Long getRowCount(Session s, Class clazz){ - CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder(); - CriteriaQuery criteria = criteriaBuilder.createQuery( Long.class ); - Root root = criteria.from( clazz ); - criteria.select( criteriaBuilder.count( root ) ); - return s.createQuery( criteria ).uniqueResult(); - } - - private void clearCounts() { - sessionFactory().getStatistics().clear(); - } - - private void assertInsertCount(int count) { - int inserts = ( int ) sessionFactory().getStatistics().getEntityInsertCount(); - assertEquals( count, inserts ); - } - - private void assertUpdateCount(int count) { - int updates = ( int ) sessionFactory().getStatistics().getEntityUpdateCount(); - assertEquals( count, updates ); - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java b/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java deleted file mode 100755 index f4e5853c14..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/ops/SimpleOpsTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.ops; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Gail Badner - */ -public class SimpleOpsTest extends AbstractOperationTestCase { - public void configure(Configuration cfg) { - super.configure( cfg ); - } - - public String[] getMappings() { - return new String[] { "ops/SimpleDynamicEntity.hbm.xml" }; - } - - @Test - public void testBasicOperations() { - clearCounts(); - - Session s = openSession(); - Transaction tx = s.beginTransaction(); - SimpleEntity entity = new SimpleEntity( ); - entity.setId( 1L ); - entity.setName( "name" ); - s.save( entity ); - tx.commit(); - s.close(); - - assertInsertCount( 1 ); - assertUpdateCount( 0 ); - assertDeleteCount( 0 ); - - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - entity = ( SimpleEntity ) s.get( SimpleEntity.class, entity.getId() ); - assertEquals( Long.valueOf( 1L ), entity.getId() ); - assertEquals( "name", entity.getName() ); - entity.setName( "new name" ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 1 ); - assertDeleteCount( 0 ); - - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - entity = ( SimpleEntity ) s.load( SimpleEntity.class, entity.getId() ); - assertFalse( Hibernate.isInitialized( entity ) ); - assertEquals( Long.valueOf( 1L ), entity.getId() ); - assertEquals( "new name", entity.getName() ); - assertTrue( Hibernate.isInitialized( entity ) ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - assertDeleteCount( 0 ); - - entity.setName( "another new name" ); - - s = openSession(); - tx = s.beginTransaction(); - s.merge( entity ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 1 ); - assertDeleteCount( 0 ); - - clearCounts(); - - s = openSession(); - tx = s.beginTransaction(); - entity = ( SimpleEntity ) s.get( SimpleEntity.class, entity.getId() ); - assertEquals( Long.valueOf( 1L ), entity.getId() ); - assertEquals( "another new name", entity.getName() ); - s.delete( entity ); - tx.commit(); - s.close(); - - assertInsertCount( 0 ); - assertUpdateCount( 0 ); - assertDeleteCount( 1 ); - } -} - diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/BaseSessionFactoryFunctionalTest.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/BaseSessionFactoryFunctionalTest.java index 4172e06406..9642c8247a 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/BaseSessionFactoryFunctionalTest.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/BaseSessionFactoryFunctionalTest.java @@ -8,9 +8,14 @@ package org.hibernate.testing.orm.junit; import java.io.IOException; import java.io.InputStream; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.NClob; +import java.util.Iterator; import java.util.function.Consumer; import java.util.function.Function; +import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataBuilder; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.SessionFactoryBuilder; @@ -22,6 +27,14 @@ import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; +import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.SimpleValue; +import org.hibernate.type.BlobType; +import org.hibernate.type.ClobType; +import org.hibernate.type.NClobType; import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl; import org.junit.jupiter.api.AfterEach; @@ -90,9 +103,62 @@ public abstract class BaseSessionFactoryFunctionalTest public MetadataImplementor produceModel(StandardServiceRegistry serviceRegistry) { MetadataSources metadataSources = new MetadataSources( serviceRegistry ); MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder(); - applyMetadataBuilder(metadataBuilder); + applyMetadataBuilder( metadataBuilder ); applyMetadataSources( metadataSources ); - return (MetadataImplementor) metadataSources.buildMetadata(); + final MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); + if ( !overrideCacheStrategy() || getCacheConcurrencyStrategy() == null ) { + return metadata; + } + + applyCacheSettings( metadata ); + + return metadata; + } + + protected final void applyCacheSettings(Metadata metadata) { + for ( PersistentClass entityBinding : metadata.getEntityBindings() ) { + if ( entityBinding.isInherited() ) { + continue; + } + + boolean hasLob = false; + + final Iterator props = entityBinding.getPropertyClosureIterator(); + while ( props.hasNext() ) { + final Property prop = (Property) props.next(); + if ( prop.getValue().isSimpleValue() ) { + if ( isLob( ( (SimpleValue) prop.getValue() ).getTypeName() ) ) { + hasLob = true; + break; + } + } + } + + if ( !hasLob ) { + ( (RootClass) entityBinding ).setCacheConcurrencyStrategy( getCacheConcurrencyStrategy() ); + entityBinding.setCached( true ); + } + } + + for ( Collection collectionBinding : metadata.getCollectionBindings() ) { + boolean isLob = false; + + if ( collectionBinding.getElement().isSimpleValue() ) { + isLob = isLob( ( (SimpleValue) collectionBinding.getElement() ).getTypeName() ); + } + + if ( !isLob ) { + collectionBinding.setCacheConcurrencyStrategy( getCacheConcurrencyStrategy() ); + } + } + } + + protected boolean overrideCacheStrategy() { + return true; + } + + protected String getCacheConcurrencyStrategy() { + return null; } protected void applyMetadataBuilder(MetadataBuilder metadataBuilder) { @@ -211,4 +277,16 @@ public abstract class BaseSessionFactoryFunctionalTest return DialectContext.getDialect(); } + private boolean isLob(String typeName) { + return "blob".equals( typeName ) + || "clob".equals( typeName ) + || "nclob".equals( typeName ) + || Blob.class.getName().equals( typeName ) + || Clob.class.getName().equals( typeName ) + || NClob.class.getName().equals( typeName ) + || BlobType.class.getName().equals( typeName ) + || ClobType.class.getName().equals( typeName ) + || NClobType.class.getName().equals( typeName ); + } + } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SessionFactoryExtension.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SessionFactoryExtension.java index 0f2f02dc9e..9a0225ba3d 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SessionFactoryExtension.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SessionFactoryExtension.java @@ -177,8 +177,6 @@ public class SessionFactoryExtension } ) ); - - } @Override