我正在使用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].

当我删除insertable或updatable关键字时,它就起作用了。我知道有很多解决方案如何使用JPA生成ID,而且JPA可以使用(调用)oracle序列来设置(生成)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没有意义(更新主键没有意义,但是可以通过原始sql来实现),但这意味着什么(您有一些有益的示例):
@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;

编辑2012-04-13

我做了一些测试:

实体
@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替换为CASE_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不是插入命令的一部分。

而且由于注释ID的原因,无法更新CASE_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.

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

最佳答案

当前,您使用JPA注释说您有一个@Id列,该列不能以任何方式插入或更新。您必须能够在插入或更新之前设置ID,但是JPA不知道如何设置。如果您不想在代码中设置ID,则需要在@Id上使用@GeneratedValue批注,以告诉JPA使用哪种策略(其中一种:TABLE,SEQUENCE,IDENTITY,AUTO)。

10-04 21:57
查看更多