diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java index f90dde51591c..bffa388f2b27 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java @@ -849,7 +849,8 @@ public final Iterator queuedAdditionIterator() { @Override public E next() { - return operationQueue.get( index++ ).getAddedInstance(); + //noinspection unchecked + return (E) operationQueue.get( index++ ).getAddedEntry(); } @Override @@ -1204,6 +1205,10 @@ protected interface DelayedOperation { void operate(); E getAddedInstance(); + + default Object getAddedEntry() { + return getAddedInstance(); + } E getOrphan(); } diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java index e8d95595c7cd..0e77c657637e 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java @@ -528,6 +528,11 @@ protected AbstractMapValueDelayedOperation(K index, E addedValue, E orphan) { protected final K getIndex() { return index; } + + @Override + public Object getAddedEntry() { + return Map.entry( getIndex(), getAddedInstance() ); + } } final class Put extends AbstractMapValueDelayedOperation { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/extralazy/ExtraLazyMapQueuedPersistTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/extralazy/ExtraLazyMapQueuedPersistTest.java new file mode 100644 index 000000000000..154f68a307c4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/extralazy/ExtraLazyMapQueuedPersistTest.java @@ -0,0 +1,132 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.extralazy; + +import java.time.LocalDate; +import java.util.TreeMap; +import java.util.SortedMap; + + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +import org.hibernate.annotations.SortNatural; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.MapKeyColumn; + + +/** + * @author Guillaume Toison + */ +@Jira( "https://hibernate.atlassian.net/browse/HHH-18885" ) +@DomainModel( annotatedClasses = { + ExtraLazyMapQueuedPersistTest.Person.class, + ExtraLazyMapQueuedPersistTest.Event.class, +} ) +@SessionFactory( useCollectingStatementInspector = true ) +public class ExtraLazyMapQueuedPersistTest { + @Test + public void testQueuedPersistOperation(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final Person person = new Person( 1L ); + + session.persist ( person ); + } ); + + scope.inTransaction( session -> { + final Person person = session.find( Person.class, 1L ); + + LocalDate date = LocalDate.of( 2024, 1, 1 ); + Event event = new Event( 1L, person, date ); + + person.getEvents().put( date, event ); + } ); + } + + @Entity( name = "Person" ) + public static class Person { + @Id + private Long id; + + @OneToMany(mappedBy = "person") + @MapKeyColumn(name = "date_col") + @SortNatural + @LazyCollection(LazyCollectionOption.EXTRA) + private SortedMap events = new TreeMap<>(); + + public Person() { + } + + public Person(Long id) { + this.id = id; + } + + public SortedMap getEvents() { + return events; + } + + public void setEvents(SortedMap events) { + this.events = events; + } + } + + @Entity( name = "Event" ) + public static class Event { + @Id + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "person_id") + private Person person; + + @Column( name="date_col" ) + private LocalDate date; + + public Event() { + } + + public Event(Long id, Person person, LocalDate date) { + this.id = id; + this.person = person; + this.date = date; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + } +}