It is possible to ignore specific entity fields from dirty check. You must override DefaultFlushEntityEventListener
like this:
@Component
public class CustomFlushEntityEventListener extends DefaultFlushEntityEventListener {
private static final List<String> IGNORE_DIRTY_CHECK_PROPERTIES = List.of(
"lastModifiedBy",
"lastModifiedDate"
);
@Override
protected void dirtyCheck(final FlushEntityEvent event) throws HibernateException {
super.dirtyCheck(event);
removeIgnoredDirtyCheckProperties(event);
}
private void removeIgnoredDirtyCheckProperties(final FlushEntityEvent event) {
var propertyNames = event.getEntityEntry().getPersister().getPropertyNames();
var dirtyProperties = event.getDirtyProperties();
if(dirtyProperties == null) return;
var newDirtyProperties = new java.util.ArrayList<Integer>();
for (int dirtyProperty : dirtyProperties) {
if (!IGNORE_DIRTY_CHECK_PROPERTIES.contains(propertyNames[dirtyProperty])) {
newDirtyProperties.add(dirtyProperty);
}
}
var newDirtyPropertiesArray = newDirtyProperties.stream().mapToInt(i -> i).toArray();
event.setDirtyProperties(newDirtyPropertiesArray.length > 0 ? newDirtyPropertiesArray : null);
}
}
and then replace listener:
@Component
@RequiredArgsConstructor
public class HibernateListenerConfigurer {
private final EntityManagerFactory entityManagerFactory;
private final CustomFlushEntityEventListener customFlushEntityEventListener;
@PostConstruct
protected void init() {
SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.FLUSH_ENTITY).clear();
registry.getEventListenerGroup(EventType.FLUSH_ENTITY).appendListener(customFlushEntityEventListener);
}
}
You can also replace IGNORE_DIRTY_CHECK_PROPERTIES
list with custom annotation on entity property for example @IgnoreDirtyCheck
and read it from event.getEntity()
by reflection.