Reputation: 5393
I am using Hibernate 4.1.3 (JPA) on the Play! framework. The database is PostgreSQL 8.4.2. The schema was generated using hibernate.hbm2ddl.auto="update"
.
Short version: I have a class that has an @Id
field that is a @GeneratedValue
. Sometimes, when persist
ing it, I get a null-column violation, why?
More details:
I have a really simple class that I want to save to the database, that looks like this:
@Entity
class MyObject {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@NotNull
public String email;
public Integer total;
}
I usually create an instance of MyObject, I assign a value to email
and total
fields while id
is null and I save it via EntityManager.persist()
. Hibernate gets an id for the new object and saves it to the DB.
However sometimes, I get the following stacktrace:
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]]
How is this possible? How can I track down the problem?
Here's the relevant DDL generated by Hibernate:
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);
Upvotes: 8
Views: 19240
Reputation: 2781
In mycase i was using Identity generation strategy and i have set the wrong data type in Postgres. Following steps i performed to debug the problem.
set
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
in application.properties and Drop the tables.
By this hibernate will automatically create the schema for you on the basis of your data-type.I noticed change in the datatype of id field.
Now when i tried any post requests, everything worked fine.
Upvotes: 0
Reputation: 201
Use Hibernate method:- save(String entityName, Object object) Persist the given transient instance, first assigning a generated identifier.
Do not use :- @GeneratedValue(strategy=GenerationType.IDENTITY) for primary key if you want to persist user define Id.
For detail:- http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/Session.html#save(java.lang.String
Upvotes: 0
Reputation: 27312
Neither the OP solution nor Matt's solution worked with my PostgreSQL 9.3.
But this one works:
@SequenceGenerator(name="identifier", sequenceName="mytable_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="identifier")
Replace mytable_id_seq
with the name of the sequence that generates your id.
Upvotes: 2
Reputation: 11805
Try the annotation @org.hibernate.annotations.GenericGenerator(name = “test-hilo-strategy”, strategy = “hilo”)
:
@Id
@org.hibernate.annotations.GenericGenerator(name=“hilo-strategy”, strategy = “hilo”)
@GeneratedValue(generator = ”hilo-strategy”)
As someone noted above, AUTO
does not do what you think. It uses the underlying DB to determine how to generate values. It may pick sequences (for oracle), identity column (for mssql), or something else that is db specific.
The approach here uses an internal strategy that Hibernate supplies called "hilo".
See chapter 5 of the Hibernate reference manual dealing with "Generator" for a full description of what each of the supplied ones does.
Upvotes: 3