当前位置: 首页 > 知识库问答 >
问题:

JPA @Id和insertable = false,updatable = false抛出异常

隆康平
2023-03-14

我正在使用 Oracle 数据库,我有序列和触发器用于在插入之前生成和存储 ID。

CREATE SEQUENCE CASE_SEQ START WITH 1001 INCREMENT BY 1 NOMAXVALUE; 

CREATE OR REPLACE TRIGGER CASE_TR_SEQ
BEFORE INSERT ON CASE FOR EACH ROW
BEGIN
  SELECT CASE_SEQ.NEXTVAL INTO :NEW.CASE_ID FROM DUAL;
END;
/

然后我有一个带有属性的简单实体:

@Id
@Column(name = "CASE_ID", insertable = false, updatable = false)
private Long caseId;

...当我尝试构建项目时,我得到:

Exception [EclipseLink-46] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):
org.eclipse.persistence.exceptions.DescriptorException
Exception Description: There should be one non-read-only mapping defined for the
primary key field [CASE.CASE_ID].

当我删除可插入或可更新的关键字时,它可以工作。我知道有很多解决方案如何使用 JPA 生成 ID,JPA 也可以使用(调用)预言机序列来设置(生成)ID。但我试图理解为什么我的解决方案是错误的。为什么我不能将这两个关键字与@Id注释一起使用?我的想法是:我想禁止JPA插入或更新caseId。

1) 什么是合适的解决方案?我应该只使用@Id:

@Id
@Column(name = "CASE_ID")
private Long caseId;

或者更好(更安全)的定义insertable=false也是:

@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;

2)我理解@Id的updatable=false没有意义(update Primary Key没有意义,但通过原始sql是可能的),但它意味着什么(有什么有益的例子吗):

@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;

我做了一些测试:

实体

@Id
@Column(name = "CASE_ID")
private Long caseId;

JPA日志

INSERT INTO CASE (CASE_ID, CASE_DATE, INFO) VALUES (?, ?, ?)
bind => [3 parameters bound]|#]

所以这是不安全的,因为JPA尝试存储CASE_ID(然后由触发器从Oracle序列中的ID替换)。

实体

@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;

创建方法

public void createCase(final Case caseData) {
    caseData.setCaseId(-1001L);
    em.persist(caseData);
}

JPA日志

INSERT INTO CASE (CASE_DATE, INFO) VALUES (?, ?)
bind => [2 parameters bound]|#]

这很好,因为CASE_ID不是insert命令的一部分。

无法更新CASE_ID,因为注释ID:

public void update() {
    Case update = em.find(Case.class, 1023L);
    update.setCaseId(1028L);
}

Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [caseId] of class
[com.wordpress.kamiluv.jsfprototype.model.entity.Case] is mapped to a primary
key column in the database. Updates are not allowed.

所以现在最后一个版本看起来是最安全的,对吧?

共有1个答案

仇和蔼
2023-03-14

您目前在JPA注释中说,您有一个不能以任何方式插入或更新的@Id列。您必须能够在插入或更新之前设置id,但是JPA不知道如何这样做。如果不希望在代码中设置Id,需要在@Id上使用@GeneratedValue注释来告诉JPA使用什么策略(TABLE、SEQUENCE、IDENTITY、AUTO之一)。

 类似资料:
  • 问题内容: 如果对字段进行了注释,这是否意味着您不能插入值或更改现有值?你为什么想这么做? 问题答案: 当创建/更新相关实体的 责任 不在 当前 实体中时,您可以这样做。例如,您有一个和一个。您想添加与实体中实体的关系,只是因为创建或更新并不是实体的责任。相反。

  • 问题内容: 如果我将字段定义为不可更新,这是否意味着该字段永远无法更新?我想做的是在保存整个实体对象时防止字段更新,但仍然能够编写显式更新此字段的查询。这可能吗? 我正在使用Hibernate和MySQL,但我更愿意编写可移植的代码。 问题答案: 作为记录,设置只影响SQL UPDATE语句 产生 的持久性提供: 该列是否包含在持久性提供程序生成的SQL UPDATE语句中。 您仍然能够编写这样的

  • 简而言之,我在数据库中有一列是这样设置的: 这样的实体: 当我像这样合并一个新实体时: 不会将field与数据库同步。它将显示<code>0</code>。我如何强制所有JPA更新数据库设置的本质上是不可变字段的内容? 其目的是创建日期字段。但还有其他场景,如由触发器设置的DB字段。。。

  • 当我检查某个元素的isDisplayed()是否等于false时,我得到的是NoTouchElementException。这是我的代码: XYZpage.java: XYZtest.java: 我在这里断言没有显示元素。我在这个网站和其他地方看到了其他的解决方案,在这些地方,人们建议尝试预期条件等。但由于元素不存在,甚至ExpectedConditions最终也不会抛出任何TouchElemen

  • 问题内容: 和JPA持久性之间有什么区别? 问题答案: Gordon Yorke(EclipseLink体系结构委员会成员,TopLink核心技术负责人,JPA 2.0专家组成员)在此主题上写了一个很好的答案,因此,我不用表述他,而是引用他的答案: 和 之间的区别是评估它们的范围。’ ‘ 的定义讨论了属性和字段值,并建议应在运行时内评估此功能。“ ”仅指数据库列。 如果实现选择实现,则这些属性应由

  • 问题内容: 我有问题.. 问题是:是不是我没有把来自 file.php的 数据仅放在最后一个div中,所以ID为9,但是现在有-所以数据在每个div中,所以这很好 但是如果我想在通过ajax加载时单击,则无法正常工作(仅在完成所有ajax-es之后) 如何解决这个问题?(也许是错误的,因为我在使用ajax。我可以使用getJSON等。) 谢谢你的帮助 问题答案: 如果希望用户在ajax调用运行时能