Skip to content

Commit

Permalink
HHH-15522 Implement a LazyInitializable interface that PersistentColl…
Browse files Browse the repository at this point in the history
…ection and Envers collections extend or implement. Improve related tests.
  • Loading branch information
fgsofis authored and yrodiere committed Sep 20, 2022
1 parent c3f1762 commit 4ac2054
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 54 deletions.
9 changes: 5 additions & 4 deletions hibernate-core/src/main/java/org/hibernate/Hibernate.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.collection.spi.LazyInitializable;

/**
* Various utility functions for working with proxies and lazy collection references.
Expand Down Expand Up @@ -85,8 +86,8 @@ public static void initialize(Object proxy) throws HibernateException {
if ( proxy instanceof HibernateProxy ) {
( (HibernateProxy) proxy ).getHibernateLazyInitializer().initialize();
}
else if ( proxy instanceof PersistentCollection ) {
( (PersistentCollection<?>) proxy ).forceInitialization();
else if ( proxy instanceof LazyInitializable ) {
( (LazyInitializable) proxy ).forceInitialization();
}
else if ( proxy instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) proxy;
Expand All @@ -111,8 +112,8 @@ else if ( proxy instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) proxy ).$$_hibernate_getInterceptor();
return !(interceptor instanceof EnhancementAsProxyLazinessInterceptor);
}
else if ( proxy instanceof PersistentCollection ) {
return ( (PersistentCollection<?>) proxy ).wasInitialized();
else if ( proxy instanceof LazyInitializable ) {
return ( (LazyInitializable) proxy ).wasInitialized();
}
else {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.collection.spi;

import org.hibernate.Incubating;

/**
* Hibernate "wraps" a java collection in an instance of PersistentCollection. Envers uses custom collection
* wrappers (ListProxy, SetProxy, etc). All of them need to extend LazyInitializable, so the
* Hibernate.isInitialized method can check if the collection is initialized or not.
*
* @author Fabricio Gregorio
*/
@Incubating
public interface LazyInitializable {

/**
* Is this instance initialized?
*
* @return Was this collection initialized? Or is its data still not (fully) loaded?
*/
boolean wasInitialized();

/**
* To be called internally by the session, forcing immediate initialization.
*/
void forceInitialization();

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* @author Gavin King
*/
@Incubating
public interface PersistentCollection<E> {
public interface PersistentCollection<E> extends LazyInitializable {
/**
* Get the owning entity. Note that the owner is only
* set during the flush cycle, and when a new collection
Expand Down Expand Up @@ -211,11 +211,6 @@ public interface PersistentCollection<E> {
*/
Serializable getSnapshot(CollectionPersister persister);

/**
* To be called internally by the session, forcing immediate initialization.
*/
void forceInitialization();

/**
* Does the given element/entry exist in the collection?
*
Expand Down Expand Up @@ -280,13 +275,6 @@ public interface PersistentCollection<E> {
*/
boolean isInitializing();

/**
* Is this instance initialized?
*
* @return Was this collection initialized? Or is its data still not (fully) loaded?
*/
boolean wasInitialized();

/**
* Called prior to the initialization of this yet-uninitialized collection. Pairs
* with {@link #afterInitialize}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import org.hibernate.collection.spi.LazyInitializable;

import org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor.Initializor;

/**
* @author Adam Warski (adam at warski dot org)
*/
public abstract class CollectionProxy<U, T extends Collection<U>> implements Collection<U>, Serializable {
public abstract class CollectionProxy<U, T extends Collection<U>> implements Collection<U>, LazyInitializable, Serializable {

private static final long serialVersionUID = 8698249863871832402L;

private transient Initializor<T> initializor;
Expand All @@ -34,6 +36,16 @@ protected void checkInit() {
}
}

@Override
public final boolean wasInitialized() {
return delegate != null;
}

@Override
public final void forceInitialization() {
checkInit();
}

@Override
public int size() {
checkInit();
Expand Down Expand Up @@ -118,7 +130,7 @@ public String toString() {
return delegate.toString();
}

@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
@SuppressWarnings({ "EqualsWhichDoesntCheckParameterClass" })
@Override
public boolean equals(Object obj) {
checkInit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.hibernate.collection.spi.LazyInitializable;
import org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor.Initializor;

/**
* @author Adam Warski (adam at warski dot org)
*/
public class MapProxy<K, V> implements Map<K, V>, Serializable {
public class MapProxy<K, V> implements Map<K, V>, LazyInitializable, Serializable {

private static final long serialVersionUID = 8418037541773074646L;

private transient Initializor<Map<K, V>> initializor;
Expand All @@ -35,6 +36,16 @@ private void checkInit() {
}
}

@Override
public final boolean wasInitialized() {
return delegate != null;
}

@Override
public final void forceInitialization() {
checkInit();
}

@Override
public int size() {
checkInit();
Expand Down Expand Up @@ -114,7 +125,7 @@ public String toString() {
}

@Override
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
@SuppressWarnings({ "EqualsWhichDoesntCheckParameterClass" })
public boolean equals(Object obj) {
checkInit();
return delegate.equals( obj );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

import org.hibernate.collection.spi.LazyInitializable;
import org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor.Initializor;

/**
* @author Adam Warski (adam at warski dot org)
*/
public class SortedMapProxy<K, V> implements SortedMap<K, V>, Serializable {
public class SortedMapProxy<K, V> implements SortedMap<K, V>, LazyInitializable, Serializable {

private static final long serialVersionUID = 2645817952901452375L;

private transient Initializor<SortedMap<K, V>> initializor;
Expand All @@ -37,6 +38,16 @@ private void checkInit() {
}
}

@Override
public final boolean wasInitialized() {
return delegate != null;
}

@Override
public final void forceInitialization() {
checkInit();
}

@Override
public int size() {
checkInit();
Expand Down Expand Up @@ -146,7 +157,7 @@ public K lastKey() {
}

@Override
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
@SuppressWarnings({ "EqualsWhichDoesntCheckParameterClass" })
public boolean equals(Object o) {
checkInit();
return delegate.equals( o );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -26,6 +28,7 @@
@Entity
@Audited
public class MultipleCollectionEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", length = 10)
Expand Down Expand Up @@ -65,7 +68,7 @@ public void setText(String text) {
}

public List<MultipleCollectionRefEntity1> getRefEntities1() {
return Collections.unmodifiableList( refEntities1 );
return refEntities1;
}

public void addRefEntity1(MultipleCollectionRefEntity1 refEntity1) {
Expand All @@ -77,7 +80,7 @@ public void removeRefEntity1(MultipleCollectionRefEntity1 refEntity1) {
}

public List<MultipleCollectionRefEntity2> getRefEntities2() {
return Collections.unmodifiableList( refEntities2 );
return refEntities2;
}

public void addRefEntity2(MultipleCollectionRefEntity2 refEntity2) {
Expand Down Expand Up @@ -110,34 +113,20 @@ public String toString() {
}

@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( !(o instanceof MultipleCollectionEntity) ) {
return false;
}

MultipleCollectionEntity that = (MultipleCollectionEntity) o;
public int hashCode() {
return Objects.hash( id );
}

if ( refEntities1 != null ? !refEntities1.equals( that.refEntities1 ) : that.refEntities1 != null ) {
return false;
}
if ( refEntities2 != null ? !refEntities2.equals( that.refEntities2 ) : that.refEntities2 != null ) {
@Override
public boolean equals(Object obj) {
if ( this == obj )
return true;
if ( obj == null )
return false;
}
if ( text != null ? !text.equals( that.text ) : that.text != null ) {
if ( getClass() != obj.getClass() )
return false;
}

return true;
MultipleCollectionEntity other = (MultipleCollectionEntity) obj;
return Objects.equals( id, other.id );
}

@Override
public int hashCode() {
int result = text != null ? text.hashCode() : 0;
result = 31 * result + (refEntities1 != null ? refEntities1.hashCode() : 0);
result = 31 * result + (refEntities2 != null ? refEntities2.hashCode() : 0);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void initData() {
}

@Test
@SuppressWarnings("unchecked")
public void testIsInitialized() {
EntityManager em = getEntityManager();

Expand All @@ -88,6 +89,10 @@ public void testIsInitialized() {
MultipleCollectionEntity ret = res.get( 0 );

assertEquals( Hibernate.isInitialized( ret.getRefEntities1() ), false );


Hibernate.initialize(ret.getRefEntities1());

assertEquals( Hibernate.isInitialized( ret.getRefEntities1() ), true );

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public void initData() {
}

@Test
@SuppressWarnings("unchecked")
public void testIsInitialized() {
EntityManager em = getEntityManager();

Expand All @@ -81,8 +82,12 @@ public void testIsInitialized() {
.getResultList();

MultipleCollectionEntity ret = res.get( 0 );

assertEquals( Hibernate.isInitialized( ret.getRefEntities1() ), false );

Hibernate.initialize(ret.getRefEntities1());

assertEquals( Hibernate.isInitialized( ret.getRefEntities1() ), true );

}
}

0 comments on commit 4ac2054

Please sign in to comment.