java ID为空时持久化实体并在数据库中自动生成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27593980/
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
Persisting an entity when ID is null and automatically generated in the database
提问by Richard Barker
I'm using EclipseLink with JavaDB and every time I try to persist a new user entity I get an error relating to the fact the ID field of the new user entity is null. I know it's null -- and it should be because the ID field is generated as the Identity in the database. Or am I wrong? I've tried adding @GeneratedValue to the entity but that causes errors regardless of the generation strategy used. I've also looked here, here, and herebut these questions don't seem to relate fully to my issue. The exceptions below always occur on at the call to EntityManager.persist(user).
我将 EclipseLink 与 JavaDB 一起使用,每次尝试保留新用户实体时,都会收到与新用户实体的 ID 字段为空这一事实相关的错误。我知道它是空的——这应该是因为 ID 字段是作为数据库中的身份生成的。还是我错了?我尝试将 @GeneratedValue 添加到实体,但无论使用的生成策略如何,都会导致错误。我也看过这里、这里和这里,但这些问题似乎与我的问题并不完全相关。下面的异常总是在调用 EntityManager.persist(user) 时发生。
I also tried removing @NotNull and @GeneratedValue and, oddly enough, it got past the persist call -- but only to fail on the commit. As far as I can tell I've got everything set right. So the question is: why is this application failing to add a new user and what do I need to do to fix it?
我还尝试删除@NotNull 和@GeneratedValue,奇怪的是,它通过了持久调用——但只是在提交时失败。据我所知,我已经把一切都设置好了。所以问题是:为什么这个应用程序无法添加新用户,我需要做些什么来修复它?
User entity:
用户实体:
@Entity(name = "User")
@Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false,unique = true)
private Long identifier;
// class shortened for brevity
}
Corresponding to this SQL Script:
对应于这个 SQL 脚本:
create table "USERSDBADMIN".USERS
(
IDENTIFIER BIGINT not null primary key GENERATED ALWAYS AS IDENTITY
(START WITH 0, INCREMENT BY 1),
USERNAME VARCHAR(50) not null,
EMAIL VARCHAR(150) not null,
LASTLOGIN DATE default NULL
);
User Create Method (from the JPA controller):
用户创建方法(来自 JPA 控制器):
public void create(User user) throws PreexistingEntityException, RollbackFailureException, Exception {
EntityManager em = null;
try {
utx.begin();
em = getEntityManager();
em.persist(user);
utx.commit();
} catch (Exception ex) {
try {
utx.rollback();
} catch (Exception re) {
throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
}
if (findUser(user.getIdentifier()) != null) {
throw new PreexistingEntityException("User " + user + " already exists.", ex);
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}
GenerationStrategy.Identity error (basically saying the ID field is null):
GenerationStrategy.Identity 错误(基本上是说 ID 字段为空):
ex = (javax.validation.ConstraintViolationException) javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
GenerationStrategy.Sequence error (Table and Auto produce same exception):
GenerationStrategy.Sequence 错误(表和自动产生相同的异常):
ex = (org.eclipse.persistence.exceptions.DatabaseException) Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException. Internal Exception: java.sql.SQLSyntaxErrorException: SEQUENCE 'SEQ_GEN_SEQUENCE' does not exist. Call: VALUES(NEXT VALUE FOR SEQ_GEN_SEQUENCE) Query: ValueReadQuery(sql="VALUES(NEXT VALUE FOR SEQ_GEN_SEQUENCE)")
回答by Lukas Risko
Do not use @NotNull
constraint on @Id
attribute generated using GenerationType.IDENTITY
strategy.
The problem is @NotNull
and other JSR-303
constraints are validated before commit.
And the autoincremented identifier isn't available until after the commit completes.
不要@NotNull
对@Id
使用GenerationType.IDENTITY
策略生成的属性使用约束。问题是在提交之前验证@NotNull
其他JSR-303
约束。并且自动增加的标识符直到提交完成后才可用。
Try this and don't care about ID initialization any more:
试试这个,不再关心 ID 初始化:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "IDENTIFIER", nullable = false, unique = true)
private Long identifier;
回答by NerosE
When I'm using auto increment at the identifier I do like this:
当我在标识符上使用自动增量时,我喜欢这样:
User user = new User();
user.setIdentifier((long) 0);// Assign 0 to ID for MSSQL/MySQL to properly auto_increment the primary key.
user.setUserName("some name");
...
With this Annotation for the id:
使用此 ID 注释:
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;