Hibernate 中,如果你想定义 只读实体(read-only entity)只读属性(read-only property),可以从几个角度入手。下面分别说明如何实现这两个目标。

一、定义只读实体

方法一:使用 @Immutable 注解

Hibernate 提供了 @org.hibernate.annotations.Immutable 注解,声明该实体为只读。被标记为只读的实体在被加载后,将不会被更新或保存。

import org.hibernate.annotations.Immutable;

import javax.persistence.Entity;

@Entity
@Immutable
public class ReadOnlyUser {
    @Id
    private Long id;

    private String username;

    // getter & setter
}

效果:

  • Hibernate 不会跟踪该实体的更改;
  • 修改该对象后调用 session.update()事务提交都不会影响数据库

方法二:使用 Hibernate 的 Session#setReadOnly(Object entity, boolean readOnly) 方法

你也可以在运行时将某个实体设置为只读:

ReadOnlyUser user = session.get(ReadOnlyUser.class, 1L);
session.setReadOnly(user, true);

注意:
这种方式是临时的,只对当前 Session 生效。

二、定义只读属性(字段)

方法一:只设置 getter,不提供 setter

Hibernate 默认使用 Java Bean 规范。如果一个字段只有 getter 没有 setter,Hibernate 将不会在更新时修改它。

@Entity
public class Product {
    @Id
    private Long id;

    private String name;

    private String readonlyField;

    public String getReadonlyField() {
        return readonlyField;
    }

    // 没有 setter
}

方法二:在映射配置中使用 insertable=false, updatable=false

这种方式可以控制属性在 INSERTUPDATE 时是否包含在 SQL 中。

@Column(name = "created_at", insertable = false, updatable = false)
private Timestamp createdAt;

说明:

  • insertable = false:不会包含在 INSERT 语句中;
  • updatable = false:不会包含在 UPDATE 语句中。

适用于数据库自动生成的字段,如 created_atversion 等。

总结表格

需求方法特点
只读实体@Immutable静态定义,全局只读
Session#setReadOnly()动态控制,临时只读
只读字段去掉 setter 方法简单粗暴,不可修改
insertable=false, updatable=false精确控制,适用于特定字段