2015-10-12 31 views
0

我有一個實體JPA @SequenceGenerator與手冊ID和自動ID

@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,休眠5和Java 8

+1

我*想*這可能是jpa的'@ GeneratedValue'如何工作(我不確定)。然而,這並不重要,因爲如果你想將生成的id與手動插入的id混合,序列[不會是最好的選擇](http://www.postgresql.org/message-id/112aab91123d2d.1123d2d112aab9 @ nyroc.rr.com)(既不是基於'int' /'bigint'的解決方案)。你應該考慮使用完全不同的東西,f.ex. 'uuid's。 – pozs

回答

0

是的,默認情況下Hibernate org.hibernate.id.SequenceGenerator總是生成新的ID。你應該做的是重寫public Serializable generate(SessionImplementor session, Object obj)方法,如果你的obj(先轉換爲你的實體)有id,那麼返回id,否則從數據庫序列中獲取它。

0

在持續,如果一個字段與@GeneratedValue註解,它會產生與被指定的任何策略的ID。然後它會用生成的值設置id字段的值。所以如果在持久化之前使用setId()手動設置id,這將被重寫。

如果需要,可以使用em.persist作爲自動生成的ID。然後使用本地SQL來手動設置Id,因爲原生SQL將繞過您對實體的任何映射。