我在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实例,我为email
和total
字段赋值,而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);
答案 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字段的数据类型发生了变化。
现在,当我尝试任何发帖请求时,一切正常。