请参考 JPA @Column 注释解释 insertable=false 和 updatable=false
Posted
技术标签:
【中文标题】请参考 JPA @Column 注释解释 insertable=false 和 updatable=false【英文标题】:Please explain about insertable=false and updatable=false in reference to the JPA @Column annotation 【发布时间】:2011-04-17 20:41:26 【问题描述】:如果一个字段被注解insertable=false, updatable=false
,是不是意味着你不能插入值,也不能改变已有的值?为什么要这样做?
@Entity
public class Person
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy="person", cascade=CascadeType.ALL)
private List<Address> addresses;
@Entity
public class Address
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
@JoinColumn(name="ADDRESS_FK")
@Column(insertable=false, updatable=false)
private Person person;
【问题讨论】:
【参考方案1】:当创建/更新引用列的责任不在当前实体中,而是在另一个实体中时,您会这样做.
【讨论】:
您是说在 Person 上使用 updatable=false 时,它将在更新地址时禁用 Person.name 的更新(我不同意,因为这是级联的目的)。您还说@Column 定义在其外键(Person)和不是外键时会有所不同(因为没有引用实体来禁用更新)。通过阅读可更新的javadoc,我会说如果它曾经被持久化,它将禁用更改给定地址的Person。你能解释一下吗? 这不是已经被级联选项充分定义了吗?我看到这被用来尝试写入生成的列而不会遇到麻烦。 (例如卷列GENERATED ALWAYS AS (height * width * length) VIRTUAL
)【参考方案2】:
当您需要在一个实体中多次映射一个字段时,定义 insertable=false, updatable=false
很有用,通常:
这不是 IMO 的语义问题,而是技术问题。
【讨论】:
我坚信这个答案比公认的要好得多。接受的答案传达了可插入/可更新属性与相关实体的创建/更新有关的感觉,而这些属性背后的真正意图是防止在当前实体中插入/更新列。相关实体的创建/更新由映射注释的级联属性处理。【参考方案3】:我想在 BalusC 和 Pascal Thivent 的答案中添加insertable=false, updatable=false
的另一个常见用法:
考虑一个不是id 而是某种序列号 的列。计算序列号的责任不一定属于应用程序。
例如,序列号从 1000 开始,每增加一个新实体就应该加一。这在数据库中很容易完成,而且非常恰当,在这种情况下,这些配置是有意义的。
【讨论】:
JPA 也支持序列,因此您也可以使用 JPA 注释定义序列。【参考方案4】:另一个示例是在“created_on”列上,您希望在该列中让数据库处理创建日期
【讨论】:
Hibernate 是否应该基于 updatable=false 注释阻止更新?在我的 JPA 存储库测试中,带有此注释的 created_on 列可以毫无怨言地接受更新。 @chrisinmtown Eclipselink 根本不会在 sql 中包含该列。我希望它与 Hibernate 相同 其实这是我的回应【参考方案5】:根据 Javax 的持久化文档:
该列是否包含在持久性提供程序生成的 SQL UPDATE 语句中。
最好从官方文档here了解。
【讨论】:
【参考方案6】:除了前面的答案之外,insertable=false, updatable=false
的一个常见用途是节省冗余的数据库查询,从而提高性能。
想象一下有一个 Client 类,它有一个 Parent 实体。如果您只想检查客户是否有父级,您只需检查其parent_id
列中是否存在值。无需让 Hibernate 获取父实体,可能还有它的所有其他关联,从而导致额外数量的查询:
public class Client
@ManyToOne(cascade = CascadeType.MERGE, CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Parent parent;
@Column(name = "parent_id", insertable = false, updatable = false)
private UUID parentId;
通过上述设置,parentId
字段将简单地获取存储在 parent_id
列中的任何值,该列仅由父实体编辑/更新。
【讨论】:
【参考方案7】:我认为这只是意味着:
该列是否包含在持久性提供程序生成的 SQL INSERT 语句中。
参考:https://www.objectdb.com/api/java/jpa/Column
【讨论】:
【参考方案8】:另一个原因可能是您的属性映射到视图的列(例如,您的休眠实体是表和视图的融合)。因此,可以插入(也不能更新)您的列是没有意义的。
@Entity
@Table(name = "THE_VIEW")
@SecondaryTable(name = "THE_TABLE", pkJoinColumns = @PrimaryKeyJoinColumn(name = "THE_ID"))
public class MyEntity
@Id
@Column(name = "THE_ID")
private Integer id;
@Column(name = "VIEW_COLUMN", updatable = false, insertable = false)
private String viewColumn
@Column(name = "TABLE_COLUMN", table = "THE_TABLE")
private String tableColumn;
(我这里不讨论可更新视图)
【讨论】:
以上是关于请参考 JPA @Column 注释解释 insertable=false 和 updatable=false的主要内容,如果未能解决你的问题,请参考以下文章