我有一个实体
@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.
答案 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,否则从数据库序列中获取它。