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

时间:2012-05-19 00:57:35

标签: java hibernate postgresql annotations 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;
}

我通常创建一个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]]

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

这是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);

4 个答案:

答案 0 :(得分:3)

尝试注释@org.hibernate.annotations.GenericGenerator(name = “test-hilo-strategy”, strategy = “hilo”)

@Id
@org.hibernate.annotations.GenericGenerator(name=“hilo-strategy”, strategy = “hilo”)
@GeneratedValue(generator = ”hilo-strategy”)

如上所述,AUTO没有按照您的想法行事。它使用底层数据库来确定如何生成值。它可能会选择序列(对于oracle),标识列(对于mssql)或其他特定于db的序列。

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

请参阅Hibernate参考手册中关于“生成器”的第5章,以获得每个提供的内容的完整描述。

答案 1 :(得分:1)

OP解决方案和Matt的解决方案都不适用于我的PostgreSQL 9.3。

但是这个有效:

@SequenceGenerator(name="identifier", sequenceName="mytable_id_seq", allocationSize=1)  
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="identifier")

mytable_id_seq替换为生成您的ID的序列名称。

答案 2 :(得分:0)

使用Hibernate方法: - save(String entityName,Object object) 保留给定的瞬态实例,首先分配生成的标识符。

如果您想要保留用户定义ID ,请不要使用: - @GeneratedValue(strategy = GenerationType.IDENTITY)作为主键。

详情如下: - http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/Session.html#save(java.lang.String

答案 3 :(得分:0)

在我的情况下,我使用的是身份生成策略,并且在Postgres中设置了错误的数据类型。按照我执行的步骤来调试问题。

设置

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true,然后放入表。

此休眠状态将根据您的数据类型自动为您创建模式。我注意到id字段的数据类型发生了变化。

现在,当我尝试任何发帖请求时,一切正常。