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 @@ -4,6 +4,7 @@
*/
package org.hibernate.event.internal;

import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.EntityEntry;
Expand Down Expand Up @@ -42,11 +43,7 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
final var holdersByKey = persistenceContext.getEntityHoldersByKey();
if ( holdersByKey != null ) {
for ( var entry : holdersByKey.entrySet() ) {
final EntityHolder holder = entry.getValue();
final EntityEntry entityEntry = holder.getEntityEntry();
final Status status = entityEntry.getStatus();
if ( status != Status.MANAGED && status != Status.GONE
|| isEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session ) ) {
if ( isEntityDirty( entry.getValue(), session ) ) {
event.setDirty( true );
return;
}
Expand All @@ -63,7 +60,18 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
}
}

private static boolean isEntityDirty(
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
final EntityEntry entityEntry = holder.getEntityEntry();
final Status status = entityEntry.getStatus();
return switch ( status ) {
case GONE, READ_ONLY -> false;
case DELETED -> true;
case MANAGED -> isManagedEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session );
case SAVING, LOADING -> throw new AssertionFailure( "Unexpected status: " + status );
};
}

private static boolean isManagedEntityDirty(
Object entity, EntityPersister descriptor, EntityEntry entityEntry, EventSource session) {
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
final Object[] propertyValues =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.Immutable;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;

@SessionFactory
@DomainModel(annotatedClasses = {IsDirtyImmutableTest.Mutable.class, IsDirtyImmutableTest.NotMutable.class})
class IsDirtyImmutableTest {
@Test
void test(SessionFactoryScope scope) {
scope.inTransaction( s -> s.persist( new Mutable() ) );
scope.inTransaction( s -> {
var entity = s.find( NotMutable.class, 1L );
assertFalse( s.isDirty() );
entity.description = "new description";
assertFalse( s.isDirty() );
} );
}

@Entity
@Table(name = "TheTable")
static class Mutable {
@Id
Long id = 1L;
String description = "old description";
}

@Immutable
@Entity
@Table(name = "TheTable")
static class NotMutable {
@Id
Long id;
String description;
}
}