【发布时间】:2026-02-06 09:00:02
【问题描述】:
我有一个带有 OneToMany 列表的实体,定义如下:
@OneToMany(
mappedBy = "fieldId",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.EAGER
)
@org.hibernate.annotations.OrderBy(clause = "sequence ASC")
public List<FieldDefinitionValue> getListOfValues()
{
return listOfValues;
}
当我从列表中删除一个项目时,当我保存父实体时,它不会从数据库中删除。
我创建了一个 CustomEntityDirtinessStrategy,这可能是它无法按预期工作的原因。在检查父实体的脏污时,我将实体报告为脏,即使唯一的更改是删除 listOfValues 中的一个或多个元素。
在 findDirty 中,我还将 listOfValues 报告为脏。
dirty = true 响应会导致不良行为(与主要问题不同,这就是为什么子实体删除根本不起作用的原因) - 对父表有不必要的更新调用。所以我怀疑我不应该将父实体本身标记为脏。我这样做是为了使子条目删除工作。
知道什么可能导致子移除失败吗?
下面是自定义的EntityDirtinessStrategy。我将它与 @DynamicUpdate 一起使用,以便 Hibernate 仅包含在其更新语句中实际更改的字段。
public class EntityDirtinessStrategy implements CustomEntityDirtinessStrategy
{
private final Logger log = Logger.getLogger(EntityDirtinessStrategy.class);
@Override
public boolean canDirtyCheck(Object entity, EntityPersister persister, Session session)
{
return entity instanceof DirtyAware;
}
@Override
public boolean isDirty(Object entity, EntityPersister persister, Session session)
{
return entity instanceof DirtyAware && ((DirtyAware)entity).isDirty();
}
@Override
public void resetDirty(Object entity, EntityPersister persister, Session session)
{
if (entity instanceof DirtyAware)
((DirtyAware)entity).commitFields();
}
@Override
public void findDirty(Object entity, EntityPersister persister, Session session, DirtyCheckContext dirtyCheckContext)
{
if (!(entity instanceof DirtyAware)) return;
DirtyAware dirtyAware = (DirtyAware)entity;
dirtyCheckContext.doDirtyChecking(
attributeInformation -> {
String propertyName = attributeInformation.getName();
boolean dirty = dirtyAware.getDirtyFields().contains(propertyName);
if (dirty) log.debug("Property "+propertyName+" is dirty.");
return dirty;
}
);
}
}
【问题讨论】:
-
CustomEntityDirtinessStrategy 是什么样子的?为什么需要它?