具有手动ID和自动ID的JPA @SequenceGenerator

时间:2015-10-12 09:57:37

标签: postgresql jpa nativequery

我有一个实体

@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)
)

我想要实现的是有时我想使用数据库生成的序列/ id,但有时数据是在其他地方创建的,我想用现有(手动)id创建。

我无法使用Spring Data JPA方式(使用CrudRepository)或JPA方式(使用EntityManager)手动设置ID,但本机查询没有问题。这是JPA的限制吗?我的问题的解决方法是什么?

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

我正在使用PostgreSQL 9.4,Hibernate 5和Java 8.

2 个答案:

答案 0 :(得分:0)

在持久化时,如果字段使用@GeneratedValue注释,它将使用指定的任何策略生成ID。然后它将使用生成的值设置id字段的值。因此,如果在持久化之前使用setId()手动设置id,则只会覆盖它。

如果需要,可以将em.persist用于自动生成的ID。然后使用本机SQL手动设置Id,因为本机SQL将绕过您在实体上的任何映射。

答案 1 :(得分:0)

是的,默认情况下,Hibernate org.hibernate.id.SequenceGenerator始终会生成新ID。你应该做的是覆盖public Serializable generate(SessionImplementor session, Object obj)方法,如果你的obj(首先强制转换为你的实体)有id,那么返回id,否则从数据库序列中获取它。