diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java index 4b29920822ee..5b1af78c985d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryHelper.java @@ -33,13 +33,12 @@ public static Serializable[] disassemble( final boolean[] nonCacheable, final SharedSessionContractImplementor session, final Object owner) { - Serializable[] disassembled = new Serializable[types.length]; + final Serializable[] disassembled = new Serializable[types.length]; for ( int i = 0; i < row.length; i++ ) { if ( nonCacheable!=null && nonCacheable[i] ) { disassembled[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY; } - else if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY - | row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) { + else if ( isPlaceholder( row[i] ) ) { disassembled[i] = (Serializable) row[i]; } else { @@ -63,10 +62,9 @@ public static Object[] assemble( final Type[] types, final SharedSessionContractImplementor session, final Object owner) { - Object[] assembled = new Object[row.length]; + final Object[] assembled = new Object[row.length]; for ( int i = 0; i < types.length; i++ ) { - if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY - || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) { + if ( isPlaceholder( row[i] ) ) { assembled[i] = row[i]; } else { @@ -76,21 +74,9 @@ public static Object[] assemble( return assembled; } -// public static Object[] assemble( -// final Object[] row, -// final Type[] types, -// final SharedSessionContractImplementor session, -// final Object owner) { -// Object[] assembled = new Object[row.length]; -// for ( int i = 0; i < types.length; i++ ) { -// if ( row[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || row[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN ) { -// assembled[i] = row[i]; -// } -// else { -// assembled[i] = types[i].assemble( (Serializable) row[i], session, owner ); -// } -// } -// return assembled; -// } + private static boolean isPlaceholder(Object value) { + return value == LazyPropertyInitializer.UNFETCHED_PROPERTY + || value == PropertyAccessStrategyBackRefImpl.UNKNOWN; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java index 455961b908ae..c595ebc20fb3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java @@ -77,14 +77,18 @@ public static void finalizeCollectionLoading( } if ( collectionDescriptor.getCollectionType().hasHolder() ) { - // in case of PersistentArrayHolder we have to realign the EntityEntry loaded state with - // the entity values + // in case of PersistentArrayHolder we have to realign + // the EntityEntry loaded state with the entity values final Object owner = collectionInstance.getOwner(); final EntityEntry entry = persistenceContext.getEntry( owner ); - final PluralAttributeMapping mapping = collectionDescriptor.getAttributeMapping(); - final int propertyIndex = mapping.getStateArrayPosition(); final Object[] loadedState = entry.getLoadedState(); - loadedState[propertyIndex] = mapping.getValue( owner ); + if ( loadedState != null ) { + final PluralAttributeMapping mapping = collectionDescriptor.getAttributeMapping(); + final int propertyIndex = mapping.getStateArrayPosition(); + loadedState[propertyIndex] = mapping.getValue( owner ); + } + // else it must be an immutable entity or loaded in read-only mode, + // but unfortunately we have no way to reliably determine that here persistenceContext.addCollectionHolder( collectionInstance ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/cache/CachedReadOnlyArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/cache/CachedReadOnlyArrayTest.java new file mode 100644 index 000000000000..0a0b5c88ad17 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/cache/CachedReadOnlyArrayTest.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.cache; + +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.Immutable; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; + +import static org.hibernate.annotations.CacheConcurrencyStrategy.READ_ONLY; + +@Jpa(annotatedClasses = CachedReadOnlyArrayTest.Publication.class) +class CachedReadOnlyArrayTest { + + @Test + void testReadFromCache(EntityManagerFactoryScope scope) { + scope.inTransaction(em -> { + Publication entity1 = new Publication(); + entity1.id = "123l"; + em.persist(entity1); + }); + scope.inTransaction(em -> em.find(Publication.class, "123l"/*, ReadOnlyMode.READ_ONLY*/)); + + } + + @Immutable + @Entity + @Cache(usage = READ_ONLY) + static class Publication { + @Id + String id; + @ElementCollection + String[] topics; + } +}