diff --git a/core/src/main/java/google/registry/model/domain/Domain.java b/core/src/main/java/google/registry/model/domain/Domain.java index 6aecfb32e5d..d6497ab37ae 100644 --- a/core/src/main/java/google/registry/model/domain/Domain.java +++ b/core/src/main/java/google/registry/model/domain/Domain.java @@ -20,7 +20,6 @@ import google.registry.model.domain.secdns.DomainDsData; import google.registry.model.host.Host; import google.registry.model.host.VKeyConverter_Host; -import google.registry.persistence.EntityCallbacksListener.RecursivePostLoad; import google.registry.persistence.VKey; import google.registry.persistence.WithVKey; import jakarta.persistence.Access; @@ -39,7 +38,6 @@ import jakarta.persistence.Table; import java.time.Instant; import java.util.Set; -import org.hibernate.Hibernate; /** * A persistable domain resource including mutable and non-mutable fields. @@ -78,9 +76,7 @@ public String getRepoId() { return super.getRepoId(); } - // It seems like this should be FetchType.EAGER, but for some reason when we do that we get a lazy - // load error during the load of a domain. - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @JoinTable( name = "DomainHost", indexes = { @@ -138,15 +134,6 @@ private Set getInternalDelegationSignerData() { return dsData; } - /** Post-load method to eager load the collections. */ - @RecursivePostLoad - protected void postLoad() { - // TODO(b/188044616): Determine why Eager loading doesn't work here. - Hibernate.initialize(dsData); - Hibernate.initialize(gracePeriods); - Hibernate.initialize(nsHosts); - } - @Override public VKey createVKey() { return VKey.create(Domain.class, getRepoId()); diff --git a/core/src/main/java/google/registry/model/domain/DomainHistory.java b/core/src/main/java/google/registry/model/domain/DomainHistory.java index 337806bb163..54426d81e38 100644 --- a/core/src/main/java/google/registry/model/domain/DomainHistory.java +++ b/core/src/main/java/google/registry/model/domain/DomainHistory.java @@ -49,7 +49,6 @@ import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; -import org.hibernate.Hibernate; /** * A persisted history entry representing an EPP modification to a domain. @@ -91,7 +90,7 @@ public Optional getDomainBase() { // We could have reused domainBase.nsHosts here, but Hibernate throws a weird exception after // we change to use a composite primary key. - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @JoinTable( name = "DomainHistoryHost", indexes = { @@ -206,12 +205,6 @@ public Period getPeriod() { @RecursivePostLoad public void domainHistoryPostLoad() { - // TODO(b/188044616): Determine why Eager loading doesn't work here. - Hibernate.initialize(domainTransactionRecords); - Hibernate.initialize(nsHosts); - Hibernate.initialize(dsDataHistories); - Hibernate.initialize(gracePeriodHistories); - if (resource != null) { resource.nsHosts = nullToEmptyImmutableCopy(nsHosts); resource.gracePeriods = diff --git a/core/src/test/java/google/registry/model/domain/DomainTest.java b/core/src/test/java/google/registry/model/domain/DomainTest.java index 45bafd62013..162ade92d89 100644 --- a/core/src/test/java/google/registry/model/domain/DomainTest.java +++ b/core/src/test/java/google/registry/model/domain/DomainTest.java @@ -20,6 +20,7 @@ import static google.registry.model.billing.BillingBase.RenewalPriceBehavior.SPECIFIED; import static google.registry.model.domain.token.AllocationToken.TokenType.BULK_PRICING; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; +import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatabaseHelper.cloneAndSetAutoTimestamps; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.newHost; @@ -238,6 +239,14 @@ void testPersistence() { String foreignKey = domain.getForeignKey(); assertThat(ForeignKeyUtils.loadResource(Domain.class, foreignKey, fakeClock.now())) .hasValue(domain); + // Verify that HQL query loading (which detaches entities on stream consumption) + // eagerly initializes all child collections before the transaction closes. + Domain loadedByStream = + tm().transact(() -> tm().loadAllOfStream(Domain.class).findFirst().orElseThrow()); + assertThat(loadedByStream.getNsHosts()).isNotEmpty(); + assertThat(loadedByStream.getGracePeriods()).isNotEmpty(); + assertThat(loadedByStream.getDsData()).isNotEmpty(); + assertThat(loadedByStream).isEqualTo(domain); } @Test diff --git a/core/src/test/java/google/registry/model/history/DomainHistoryTest.java b/core/src/test/java/google/registry/model/history/DomainHistoryTest.java index 6e8e883cad7..75d8069f5e8 100644 --- a/core/src/test/java/google/registry/model/history/DomainHistoryTest.java +++ b/core/src/test/java/google/registry/model/history/DomainHistoryTest.java @@ -14,6 +14,7 @@ package google.registry.model.history; +import static com.google.common.collect.MoreCollectors.onlyElement; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; @@ -66,6 +67,15 @@ void testPersistence() { assertDomainHistoriesEqual(fromDatabase, domainHistory); assertThat(fromDatabase.getRepoId()).isEqualTo(domainHistory.getRepoId()); }); + // Verify that HQL query loading (which detaches entities on stream consumption) + // eagerly initializes all child collections before the transaction closes. + DomainHistory loadedByStream = + tm().transact(() -> tm().loadAllOfStream(DomainHistory.class).collect(onlyElement())); + assertThat(loadedByStream.getNsHosts()).isNotEmpty(); + assertThat(loadedByStream.getDsDataHistories()).isNotEmpty(); + assertThat(loadedByStream.getGracePeriodHistories()).isNotEmpty(); + assertThat(loadedByStream.getDomainTransactionRecords()).isNotEmpty(); + assertDomainHistoriesEqual(loadedByStream, domainHistory); } @Test