Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ protected boolean readSize() {
session.getPersistenceContextInternal().getCollectionEntry( this );
if ( entry != null ) {
final CollectionPersister persister = entry.getLoadedPersister();
checkPersister( this, persister );
if ( persister.isExtraLazy() ) {
// TODO: support for extra-lazy collections was
// dropped so this code should be obsolete
Expand Down Expand Up @@ -331,6 +332,7 @@ protected Boolean readIndexExistence(final Object index) {
() -> {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( this );
final CollectionPersister persister = entry.getLoadedPersister();
checkPersister( this, persister );
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
session.flush();
Expand All @@ -353,6 +355,7 @@ protected Boolean readElementExistence(final Object element) {
() -> {
final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( this );
final CollectionPersister persister = entry.getLoadedPersister();
checkPersister( this, persister );
if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) {
session.flush();
Expand Down Expand Up @@ -399,6 +402,7 @@ public Object doWork() {
session.getPersistenceContextInternal()
.getCollectionEntry( AbstractPersistentCollection.this );
final CollectionPersister persister = entry.getLoadedPersister();
checkPersister( AbstractPersistentCollection.this, persister );
isExtraLazy = persister.isExtraLazy();
if ( isExtraLazy ) {
if ( hasQueuedOperations() ) {
Expand Down Expand Up @@ -646,12 +650,22 @@ private void throwLazyInitializationExceptionIfNotConnected() {
}

private void throwLazyInitializationException(String message) {
throwLazyInitializationException( role, message);
}

private static void throwLazyInitializationException(String role, String message) {
throw new LazyInitializationException(
String.format( "Cannot lazily initialize collection%s (%s)",
role == null ? "" : " of role '" + role + "'", message )
);
}

public static void checkPersister(PersistentCollection collection, CollectionPersister persister) {
if ( !collection.wasInitialized() && persister == null ) {
throwLazyInitializationException( null, "collection is being removed" );
}
}

protected final void setInitialized() {
this.initializing = false;
this.initialized = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.hibernate.sql.results.internal.ResultsHelper;
import org.hibernate.stat.spi.StatisticsImplementor;

import static org.hibernate.collection.spi.AbstractPersistentCollection.checkPersister;
import static org.hibernate.loader.internal.CacheLoadHelper.initializeCollectionFromCache;
import static org.hibernate.pretty.MessageHelper.collectionInfoString;

Expand All @@ -41,6 +42,7 @@ public void onInitializeCollection(InitializeCollectionEvent event) throws Hiber
}
if ( !collection.wasInitialized() ) {
final CollectionPersister loadedPersister = ce.getLoadedPersister();
checkPersister(collection, loadedPersister);
final Object loadedKey = ce.getLoadedKey();
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Initializing collection "
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.events;


import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import org.hibernate.HibernateException;
import org.hibernate.event.spi.EventType;

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 java.util.HashSet;
import java.util.Set;
import java.util.UUID;

import static jakarta.persistence.FetchType.LAZY;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* @author Felix König
* @author Jan Schatteman
*/
@DomainModel (
annotatedClasses = {
PreDeleteEventListenerTest.Parent.class, PreDeleteEventListenerTest.Child.class
}
)
@SessionFactory
@Jira( value = "https://hibernate.atlassian.net/browse/HHH-19631" )
public class PreDeleteEventListenerTest {

@Test
void testAccessUninitializedCollectionInListener(SessionFactoryScope scope) {

scope.getSessionFactory().getEventListenerRegistry().appendListeners( EventType.PRE_DELETE,
event -> {
Parent parent = ((Parent) event.getEntity());
// dummy access
assertThrows( HibernateException.class, () -> parent.getChildren().size() );
return false;
}, event -> {
Parent parent = ((Parent) event.getEntity());
// dummy access
assertThrows( HibernateException.class, () -> parent.getChildren().contains(new Child()) );
return false;
} );

scope.inTransaction( session -> session.persist(new Parent()) );

scope.inTransaction(session -> {
var parent = session.createSelectionQuery("select p from Parent p", Parent.class).getSingleResult();
// triggers pre-delete event
session.remove(parent);
session.flush();
});
}

@Entity(name= "Parent")
public static class Parent {
@Id String id = UUID.randomUUID().toString();
@ManyToMany(fetch = LAZY)
Set<Child> children = new HashSet<>();
public Set<Child> getChildren() {
return children;
}
}

@Entity(name= "Child")
public static class Child {
@Id
String childId = UUID.randomUUID().toString();
}

}
Loading