我一直试图弄清楚如何解决这个问题。很糟糕的是,hibernate没有提供准备使用注释来从脏检查中排除属性。 这是问题,我有一个课程如下
Class A {
@Column
Property 1
@Column
Property 2..etc
@Column
Date lastUpdateDate
@Column
String lastUpdateBy
}
我想从脏检查中排除lastUpdateDate和lastUpdateBy! 这就是我正在做的事情
使用Dynamic-Update = true
使用拦截器和覆盖findDirty方法来告诉hibernate对象是否脏(这里,previousState总是为null因为对象是瞬态的,所以无法比较旧值)
merge会修复这个问题,但它会导致性能问题(几百万条记录)所以我必须使用saveOrUpdate,它不会将previousState传递给Interceptor
还有其他方法可以解决这个问题吗?
答案 0 :(得分:1)
答案 1 :(得分:1)
您可以使用@OptimisticLock(excluded = true)
将其从脏检查中排除。
答案 2 :(得分:1)
可以从脏检查中忽略特定的实体字段。您必须像这样覆盖DefaultFlushEntityEventListener
:
@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);
}
}
,然后替换侦听器:
@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);
}
}
您还可以将IGNORE_DIRTY_CHECK_PROPERTIES
列表替换为实体属性上的自定义注释,例如@IgnoreDirtyCheck
,并通过反射从event.getEntity()
中读取。
答案 3 :(得分:0)
你应该使用hibernate / JPA实体监听器来更新你的属性(lastUpdateDate)
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html
它比使用自己的脏检查更容易使用标准解决方案。