You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于字段值将持久化实体设为不可变的Hibernate实现方案问询

基于字段值实现Hibernate实体不可变控制

一、标记实体不可变的方式

在实体类中添加映射到数据库的布尔字段,用来标识记录是否不可变,示例如下:

@Entity
@Table(name = "business_data")
public class BusinessData {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 不可变标记:true表示该记录禁止增删改
    @Column(name = "is_immutable", nullable = false)
    private boolean immutable;

    // 其他业务字段
    private String content;

    // getter/setter
    public boolean isImmutable() {
        return immutable;
    }

    public void setImmutable(boolean immutable) {
        this.immutable = immutable;
    }

    // 其余字段的getter/setter省略
}

二、阻止Hibernate执行增删改的原生方案

使用Hibernate的事件监听器替代旧版拦截器,通过PreInsertEventListener、PreUpdateEventListener、PreDeleteEventListener在操作执行前校验不可变标记,直接跳过对应操作,不会触发事务回滚或意外删除。

1. 实现自定义事件监听器

public class ImmutableEntityControlListener implements PreInsertEventListener, PreUpdateEventListener, PreDeleteEventListener {

    @Override
    public boolean onPreInsert(PreInsertEvent event) {
        return checkAndSkipImmutable(event.getEntity());
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {
        return checkAndSkipImmutable(event.getEntity());
    }

    @Override
    public boolean onPreDelete(PreDeleteEvent event) {
        return checkAndSkipImmutable(event.getEntity());
    }

    private boolean checkAndSkipImmutable(Object entity) {
        // 仅对目标实体类做校验
        if (entity instanceof BusinessData) {
            BusinessData data = (BusinessData) entity;
            if (data.isImmutable()) {
                // 返回true告知Hibernate:该操作已处理,无需继续执行
                return true;
            }
        }
        // 返回false:Hibernate正常执行后续操作
        return false;
    }
}

2. 注册监听器到Hibernate

根据项目环境选择注册方式:

Spring Boot 环境

通过HibernatePropertiesCustomizer注入监听器:

@Component
public class HibernateListenerRegistrar implements HibernatePropertiesCustomizer {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void customize(Map<String, Object> hibernateProperties) {
        EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
                .getServiceRegistry().getService(EventListenerRegistry.class);
        
        registry.appendListeners(EventType.PRE_INSERT, new ImmutableEntityControlListener());
        registry.appendListeners(EventType.PRE_UPDATE, new ImmutableEntityControlListener());
        registry.appendListeners(EventType.PRE_DELETE, new ImmutableEntityControlListener());
    }
}
原生Hibernate 环境

在构建SessionFactory时注册:

Configuration config = new Configuration().configure();
config.setListener("pre-insert", new ImmutableEntityControlListener());
config.setListener("pre-update", new ImmutableEntityControlListener());
config.setListener("pre-delete", new ImmutableEntityControlListener());

SessionFactory sessionFactory = config.buildSessionFactory();

方案优势

  • 覆盖全操作:同时拦截插入、更新、删除,解决setter仅能阻止更新的局限
  • 无事务风险:通过返回true跳过操作,无需抛出异常,不会影响事务内其他合法操作
  • 零业务侵入:无需在服务层或实体setter中编写校验逻辑,完全基于Hibernate原生机制实现

内容的提问来源于stack exchange,提问作者Jing Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:22:20