使用@GeneratedValue对@Id进行Hibernate空约束违规

Giu*_*one 7 java postgresql annotations hibernate playframework

我在Play上使用Hibernate 4.1.3(JPA)!框架.数据库是PostgreSQL 8.4.2.模式是使用生成的hibernate.hbm2ddl.auto="update".

简短版本:我有一个有一个@Id字段的类@GeneratedValue.有时,当persist它出现时,我得到一个空列违规,为什么?


更多细节:

我有一个非常简单的类,我想保存到数据库,看起来像这样:

@Entity
class MyObject {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long id;

    @NotNull
    public String email;

    public Integer total;
}
Run Code Online (Sandbox Code Playgroud)

我通常创建MyObject的实例,我把值赋给emailtotal领域,同时id为空,我通过保存它EntityManager.persist().Hibernate获取新对象的id并将其保存到DB.

但有时,我得到以下堆栈跟踪:

2012-05-19 00:45:16,335 - [ERROR] - from org.hibernate.engine.jdbc.spi.SqlExceptionHelper [SqlExceptionHelper.java:144] in play-akka.actor.actions-dispatcher-6 
ERROR: null value in column "id" violates not-null constraint

2012-05-19 00:45:16,350 - [ERROR] - from application in play-akka.actor.actions-dispatcher-6 


! @6ad7j3p8p - Internal server error, for request [POST /method] ->

play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[PersistenceException: org.hibernate.exception.ConstraintViolationException: ERROR: null value in column "id" violates not-null constraint]]
Run Code Online (Sandbox Code Playgroud)

这怎么可能?我该如何追踪问题?

这是Hibernate生成的相关DDL:

CREATE TABLE myobject (
    id bigint NOT NULL,
    email character varying(255) NOT NULL,
    physical integer
);

CREATE SEQUENCE hibernate_sequence
    START WITH 1
    INCREMENT BY 1
    NO MAXVALUE
    NO MINVALUE
    CACHE 1;


ALTER TABLE ONLY dailydetailedscore
    ADD CONSTRAINT dailydetailedscore_pkey PRIMARY KEY (id);
Run Code Online (Sandbox Code Playgroud)

Mat*_*att 3

尝试注释@org.hibernate.annotations.GenericGenerator(name = \xe2\x80\x9ctest-hilo-strategy\xe2\x80\x9d, strategy = \xe2\x80\x9chilo\xe2\x80\x9d)

\n\n
@Id\n@org.hibernate.annotations.GenericGenerator(name=\xe2\x80\x9chilo-strategy\xe2\x80\x9d, strategy = \xe2\x80\x9chilo\xe2\x80\x9d)\n@GeneratedValue(generator = \xe2\x80\x9dhilo-strategy\xe2\x80\x9d)\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如上面有人指出的那样,AUTO不会按照您的想法行事。它使用底层数据库来确定如何生成值。它可能会选择序列(对于 oracle)、标识列(对于 mssql)或其他特定于数据库的内容。

\n\n

这里的方法使用 Hibernate 提供的称为“hilo”的内部策略。

\n\n

请参阅 Hibernate 参考手册中有关“生成器”的第 5 章,以获取所提供的每个生成器功能的完整描述。

\n

  • 实际上,AUTO 策略做了它在 Postgres 上应该做的事情(即使用序列生成唯一标识符)。事实证明,我的代码在 PostgreSQL 8.4.4 上运行良好,因此我认为这是一个特定于版本的错误。hilo 生成器在 8.4.2 上运行得很好,所以我将使用它。 (2认同)