【问题标题】:JPA @SequenceGenerator with Manual ID and Auto ID具有手动 ID 和自动 ID 的 JPA @SequenceGenerator
【发布时间】:2016-01-09 18:20:56
【问题描述】:

我有一个实体

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

有架构

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。

【问题讨论】:

  • 认为这可能是 jpa 的 @GeneratedValue 的工作方式(我不确定)。但是,这并不重要,因为如果您想将生成的 id 与手动插入的 id 混合,则需要使用序列 won't be the best choice(任何基于 int/bigint 的解决方案)。你应该考虑使用完全不同的东西,f.ex。 uuids.

标签: postgresql jpa nativequery


【解决方案1】:

是的,默认情况下 Hibernate org.hibernate.id.SequenceGenerator 总是生成新的 id。你应该做的是重写public Serializable generate(SessionImplementor session, Object obj)方法,如果你的obj(首先转换到你的实体)有id,然后返回id,否则从数据库序列中获取。

【讨论】:

  • 如果新生成的 id 已经被占用了怎么办,因为它是手动插入的?现在,它会抛出一个duplicate key value violates unique constraint 你有解决方案吗?
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多