mirror of
https://github.com/google/nomulus.git
synced 2025-08-04 17:01:51 +02:00
Copy DTRs into PersistentSet field if applicable in HistoryEntry (#1456)
In replay (and possibly in other cases) we're getting an exception: Caused by: org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: google.registry.model.domain.DomainHistory.internalDomainTransactionRecords The main cause of this, according to research (StackOverflow :P) is that when Hibernate is calling the setters for these sets of children it's losing the connection to the previously-managed child entity (which it needs, in order to know how to delete orphans). Thus, the solution is to maintain the same instance of the persistent set and just add/remove to/from it as necessary. This is complicated by the fact that sometimes the setter is given the persistent set (the one we want to keep) and sometimes (?) it isn't. We will need to try this out to be sure.
This commit is contained in:
parent
a96db1f236
commit
7a5ff79cb1
2 changed files with 20 additions and 4 deletions
|
@ -209,7 +209,7 @@ public class DomainHistory extends HistoryEntry implements SqlEntity {
|
|||
@SuppressWarnings("unused")
|
||||
private void setInternalDomainTransactionRecords(
|
||||
Set<DomainTransactionRecord> domainTransactionRecords) {
|
||||
this.domainTransactionRecords = domainTransactionRecords;
|
||||
super.setDomainTransactionRecords(domainTransactionRecords);
|
||||
}
|
||||
|
||||
@Id
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.model.reporting;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.googlecode.objectify.Key.getKind;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
|
@ -63,6 +64,7 @@ import javax.persistence.Enumerated;
|
|||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.hibernate.collection.internal.PersistentSet;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
|
@ -317,9 +319,23 @@ public class HistoryEntry extends ImmutableObject
|
|||
|
||||
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setDomainTransactionRecords(Set<DomainTransactionRecord> domainTransactionRecords) {
|
||||
this.domainTransactionRecords =
|
||||
domainTransactionRecords == null ? null : ImmutableSet.copyOf(domainTransactionRecords);
|
||||
protected void setDomainTransactionRecords(
|
||||
Set<DomainTransactionRecord> domainTransactionRecords) {
|
||||
// Note: how we wish to treat this Hibernate setter depends on the current state of the object
|
||||
// and what's passed in. The key principle is that we wish to maintain the link between parent
|
||||
// and child objects, meaning that we should keep around whichever of the two sets (the
|
||||
// parameter vs the class variable and clear/populate that as appropriate.
|
||||
//
|
||||
// If the class variable is a PersistentSet and we overwrite it here, Hibernate will throw
|
||||
// an exception "A collection with cascade=”all-delete-orphan” was no longer referenced by the
|
||||
// owning entity instance". See https://stackoverflow.com/questions/5587482 for more details.
|
||||
if (this.domainTransactionRecords instanceof PersistentSet) {
|
||||
Set<DomainTransactionRecord> nonNullRecords = nullToEmpty(domainTransactionRecords);
|
||||
this.domainTransactionRecords.retainAll(nonNullRecords);
|
||||
this.domainTransactionRecords.addAll(nonNullRecords);
|
||||
} else {
|
||||
this.domainTransactionRecords = domainTransactionRecords;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue