Giuseppe Cardone
Giuseppe Cardone

Reputation: 5393

Hibernate null constraint violation on @Id with @GeneratedValue

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 persisting 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

Answers (4)

AConsumer
AConsumer

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

Vinit Bhardwaj
Vinit Bhardwaj

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

bluish
bluish

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

Matt
Matt

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

Related Questions