I am trying to define a parent entity and a child collection
public class Parent {
private Set<Child> children;
}
And the moment I try to remove child, for example, I am getting UnsupportedOperationException due to the reason, that the collection is initialized by Hibernate as PersistentSet which is immutable and clear() or remove() methods throw this exception.
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ApplicationScoped
@Transactional(Transactional.TxType.REQUIRED)
public class SubscriptionRepository implements PanacheRepository<SubscriptionEntity> {
And I have the following code : which returns different errors as follows :
// Step 2: Copy the child collection to a new mutable Set
Set<SubscriptionLicenseEntity> currentLicenses = existing.getLicenses();
Set<SubscriptionLicenseEntity> updatedLicenses = new HashSet<>(currentLicenses);
// Step 3: Remove the elements you want from the copied Set
// For example, removing the first element
Optional<SubscriptionLicenseEntity> licenseToRemove = updatedLicenses.stream().findFirst();
if (licenseToRemove.isPresent()) {
updatedLicenses.remove(licenseToRemove.get());
// If the entity is managed (attached), delete the license directly
subscriptionLicenseRepository.delete(licenseToRemove.get());
}
// Step 4: Reassign the updated collection back to the parent entity
existing.setLicenses(updatedLicenses); // Reassign the modified set
/*
Throws : .hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.qualibooth.entity.SubscriptionEntity.licenses
at .hibernate.engine.internal.Collections.processDereferencedCollection(Collections.java:98)
at .hibernate.engine.internal.Collections.processUnreachableCollection(Collections.java:49)
at .hibernate.event.internal.AbstractFlushingEventListener.lambda$flushCollections$1(AbstractFlushingEventListener.java:265)
at .hibernate.engine.internal.StatefulPersistenceContext.forEachCollectionEntry(StatefulPersistenceContext.java:1114)
*/
// Step 2: Get the existing collection (do not create a new collection)
Set<SubscriptionLicenseEntity> currentLicenses = existing.getLicenses();
// Step 3: Remove the elements directly from the existing collection
Optional<SubscriptionLicenseEntity> licenseToRemove = currentLicenses.stream().findFirst();
if (licenseToRemove.isPresent()) {
SubscriptionLicenseEntity license = licenseToRemove.get();
currentLicenses.remove(license); // Remove directly from the existing collection
// Step 4: Delete the license entity from the database
subscriptionLicenseRepository.delete(license);
}
/*
Throws : java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.remove(ImmutableCollections.java:150)
at .hibernate.collection.spi.PersistentSet.remove(PersistentSet.java:212)
*/
// Step 2: Get the existing licenses
Set<SubscriptionLicenseEntity> currentLicenses = existing.getLicenses();
// Step 3: Create a new mutable set and copy the licenses
Set<SubscriptionLicenseEntity> licensesToRemove = new HashSet<>();
Optional<SubscriptionLicenseEntity> licenseToRemove = currentLicenses.stream().findFirst();
if (licenseToRemove.isPresent()) {
licensesToRemove.add(licenseToRemove.get());
// Step 4: Remove from the current collection
currentLicenses.removeAll(licensesToRemove);
// Step 5: Explicitly delete the orphaned licenses
licensesToRemove.forEach(subscriptionLicenseRepository::delete);
// Step 6: Clear the original collection and re-add the modified licenses
existing.getLicenses().clear(); // Clear the original set
existing.getLicenses().addAll(currentLicenses); // Add the updated licenses back
}
/*
Throws : java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.removeAll(ImmutableCollections.java:151)
at .hibernate.collection.spi.PersistentSet.removeAll(PersistentSet.java:291)
*/
subscriptionRepository.persist(existing);