java JPA @Id 和 insertable = false,可更新 = false 抛出异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10128092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA @Id and insertable = false, updatable = false throws exception
提问by Ziletka
I'm using Oracle database and I have sequence and trigger for generating and storing ID before insert.
我正在使用 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;
/
Then I have simple entity with property:
然后我有一个带有属性的简单实体:
@Id
@Column(name = "CASE_ID", insertable = false, updatable = false)
private Long caseId;
...when I try build project I'm getting:
...当我尝试构建项目时,我得到:
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].
When I remove either insertable or updatable keyword, then it works. I know that there is a lot of solutions how generate ID using JPA, also JPA can use (call) oracle sequence to set (generated) ID. But I try understand why is my solutions wrong. Why I can't use both keywords together with the @Id annotation? My thought is: I want to prohibit insert or update caseId by JPA.
当我删除可插入或可更新关键字时,它就会起作用。我知道有很多解决方案如何使用 JPA 生成 ID,JPA 也可以使用(调用)oracle 序列来设置(生成)ID。但我试着理解为什么我的解决方案是错误的。为什么我不能将这两个关键字与 @Id 注释一起使用?我的想法是:我想禁止 JPA 插入或更新 caseId。
1) What is the proper soulution? Should I use only @Id:
1)什么是正确的解决方案?我应该只使用@Id:
@Id
@Column(name = "CASE_ID")
private Long caseId;
or is better (safer) define insertable=false also:
或者更好(更安全)也定义 insertable=false :
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
2) I understand that updatable=false for @Id does not have meaning (update Primary Key does not have meaning but it is possible by raw sql), but what does it mean (do you have some example when it is beneficial):
2)我知道 @Id 的 updatable=false 没有意义(更新主键没有意义,但原始 sql 可能),但它是什么意思(你有一些有益的例子):
@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;
EDIT 2012-04-13
编辑 2012-04-13
I made some tests:
我做了一些测试:
Entity
实体
@Id
@Column(name = "CASE_ID")
private Long caseId;
JPA log
JPA日志
INSERT INTO CASE (CASE_ID, CASE_DATE, INFO) VALUES (?, ?, ?)
bind => [3 parameters bound]|#]
So this is not safe, because JPA tries store CASE_ID (which is then replaced by ID from Oracle sequence by trigger).
所以这不安全,因为 JPA 尝试存储 CASE_ID(然后通过触发器将其替换为 Oracle 序列中的 ID)。
Entity
实体
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
Create method
创建方法
public void createCase(final Case caseData) {
caseData.setCaseId(-1001L);
em.persist(caseData);
}
JPA log
JPA日志
INSERT INTO CASE (CASE_DATE, INFO) VALUES (?, ?)
bind => [2 parameters bound]|#]
It is good, because the CASE_ID is not part of insert command.
这很好,因为 CASE_ID 不是插入命令的一部分。
And Update of CASE_ID is not possible because annotation ID:
并且无法更新 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.
So now the last version looks as the most safe, right?
所以现在最后一个版本看起来最安全,对吧?
采纳答案by bobz32
You are currently saying with your JPA annotations that you have an @Id column that cannot be inserted or updated in any way. You must be able to set the id before inserting or updating, but JPA does not know how to do so. You will need to use the @GeneratedValue annotation on the @Id to tell JPA what strategy to use (one of: TABLE,SEQUENCE,IDENTITY,AUTO) if you do not want the id to be set in your code.
您当前使用 JPA 注释说您有一个无法以任何方式插入或更新的 @Id 列。您必须能够在插入或更新之前设置 id,但 JPA 不知道如何设置。如果您不希望在代码中设置 id,则需要在 @Id 上使用 @GeneratedValue 注释来告诉 JPA 要使用什么策略(其中之一:TABLE、SEQUENCE、IDENTITY、AUTO)。