28

I am using Hibernate 3.3 and PostgreSQL 8.x and would like to use Hibernate annotations to map an auto-incremented column which is NOT a primary key.

It doesn't matter if the column is mapped using SERIAL type or sequences in Postgres as long as it gets auto-incremented by the database and not by Hibernate. I tried the following mappings, but they always generated null orderId.

@Column(name = "orderId", insertable = false)
@Generated(GenerationTime.INSERT)
//@GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
private Integer orderId;

I will appreciate any help with this.

Thanks

3
  • Are you sure it's null? How did you determined it? Commented Feb 12, 2011 at 18:26
  • I wrote an integration test and checked this field's value in the debugger. Commented Feb 12, 2011 at 18:47
  • @alecswan please revise the selected answer - i believe my answer is more correct and i personally have to keep coming back here to remember how to do it correctly! every time i attempt to use the incorrect answer and then look further and find my own correct answer! Commented Jun 27, 2014 at 1:58

5 Answers 5

37

The following mapping should work fine:

@Column(name = "orderId")
@Generated(GenerationTime.INSERT)
private Integer orderId;

Note, however, that generated value for freshly saved objects is not available until session is flushed.

EDIT: Note that this mapping doesn't affect doesn't make Hibernate to create a column of type serial during schema generation, since Hibernate doesn't know anything about the nature of value generation at the database side. Therefore, if you want Hibernate to create a column with a proper type, you need to specifiy it explicitly:

@Column(name = "orderId", columnDefinition = "serial")
@Generated(GenerationTime.INSERT)
private Integer orderId;

And on a recent Hibernate version (4.3), you can use this:

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long orderId;
Sign up to request clarification or add additional context in comments.

9 Comments

Flushing the session before loading the object did not work. I noticed that Hibernate just generates orderid column with type INTEGER in Postgres database. I don't see how this can work at all if the type is not SERIAL and Hibernate does not generate any triggers that would update this column. Any other thoughts? Thanks
@alecswan: Updated. Also, flushing is related to the session where objects were save, not the the session where they are loaded.
In my case objects were saved and loaded in the same session. Adding columnDefinition = "serial" fixed the problem, thanks! Is there a solution, e.g. using Identity generator, to make this solution work on other databases as well?
@alecswan: As far as I know, Hibernate doesn't support generators for non-id properties.
up-vote because this can be used for generating values on non-id columns. And that can be a big issue. This makes it easy with the downside of being hibernate specific (and not JPA) and Database specific (PostgreSQL). In my case that is not an issue.
|
25

the accepted answer doesn't work for me.

this did though:

@Id
@Column(name = "your_id", columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer yourId;

5 Comments

this is also JPA not compatible which is a bonus.
How is not compatible a bonus?
Works for me, without the columnDefinition = "serial", I prefer to declare this only in the SQL generation file, using flyway (or liquibase)
Wait, didn't OP say his column is NOT a primary key? Does @Id annotation still apply in such case?
@Klesun i must have missed that requirement - oops
5

I'm using this with postgresql9.1, should work with 8 too:

@SequenceGenerator(allocationSize=1, initialValue=1, sequenceName="account_id_seq", name="account_id_seq")
@GeneratedValue(generator="account_id_seq", strategy=GenerationType.SEQUENCE)
@Id
@Column(name="id")
private Integer id;

2 Comments

You can also use strategy=GenerationType.IDENTITY
Does this work without @Id? (Because the question is explicit about the field not being an id field)
1

I tried both GenerationTime.INSERT and GenerationType.IDENTITY, but neither prevented the null from being inserted on an updating saveAll() call.

What did help was marking the field as non-writable for hibernate:

@Column(insertable = false, updatable = false)
private Integer orderId;

(Kudos to this answer)

Comments

0

Database sequence is not sync with your private key. So you need to update sequence index.

Check your sequence id from db and execute this sql command. (Do not forget to get backup your db just in case)

SELECT setval('your_primary_key_sequence', (SELECT MAX(your_primary_key) FROM your_table)+1);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.