0

I have an entity

@Entity
public class Book {

    @Id
    @Column(name = "book_id")
    @SequenceGenerator(name = "book_book_id_seq", sequenceName = "book_book_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_book_id_seq")
    private Long id;

    // getter, setter & other fields
}

with schema

CREATE TABLE book
(
  book_id bigint NOT NULL DEFAULT nextval('book_book_id_seq'::regclass),
  CONSTRAINT book_pkey PRIMARY KEY (book_id)
)

What I want to achieve is sometime I would like to use sequence/id generated by database, but sometime the data is created at other place and I would like to create with existing (manual) id.

I can't set the id manually with Spring Data JPA way (using CrudRepository) or JPA way (using EntityManager), but no issue with native query. Is this JPA limitation? Any workaround for my issue?

Book book01 = new Book();
bookRepo.save(book01); // Book with id 1 is created

Book book02 = new Book();
book02.setId(5555L);

bookRepo.save(book02); // Does not create book with id 5555, but 2

Query nativeQuery = entityManager.createNativeQuery("INSERT INTO book VALUES (6666);");
nativeQuery.executeUpdate(); // Book with id 6666 is created

Query nativeQuery02 = entityManager.createNativeQuery("INSERT INTO book DEFAULT VALUES;");
nativeQuery02.executeUpdate(); // Book with id 3 is created

I am using PostgreSQL 9.4, Hibernate 5 and Java 8.

Lee Chee Kiam
  • 11,450
  • 10
  • 65
  • 87
  • 1
    I *think* this might be how jpa's `@GeneratedValue` works (I'm not sure). However, this does not matter, because if you want to mix generated ids with manually inserted ones, a sequence [won't be the best choice](http://www.postgresql.org/message-id/112aab91123d2d.1123d2d112aab9@nyroc.rr.com) (neither any `int`/`bigint` based solution). You should consider using something entirely different, f.ex. `uuid`s. – pozs Oct 12 '15 at 10:40

2 Answers2

1

On persist, if a field is annotated with @GeneratedValue, it will generate the ID with whatever strategy is specified. Then it will set value of the id field with the generated value. So if the id is manually set using setId() before persisting, this will just be overriden.

If you want, you can use em.persist for auto-generated IDs. Then use native SQL for manually setting the Id, since native SQLs will bypass whatever mapping you have on your entity.

Ish
  • 3,992
  • 1
  • 17
  • 23
1

Yes, by default Hibernate org.hibernate.id.SequenceGenerator always generate new id. What you should do is to override public Serializable generate(SessionImplementor session, Object obj) method, where if your obj (cast to your entity first) has id, then return the id, else get it from database sequence.

Lee Chee Kiam
  • 11,450
  • 10
  • 65
  • 87
  • And what if new generated id is already taken, because it was manually inserted? For now, it throws a `duplicate key value violates unique constraint` Do you have a solution for this? – alexander Dec 06 '19 at 17:02