2017-09-04 32 views
2

エンティティをHibernateにマップしようとしていますが、SQL Serverを使用しています。埋め込みキーにSQL ServerのID列が含まれていると、Hibernateの挿入に失敗する

以下は詳細です。

SQL Serverのエンティティ

CREATE TABLE [dbo].[BOOK_EMBEDDED](

[row_id] [bigint] IDENTITY(1,1) NOT NULL, 

[group_no] [int] NOT NULL, 

[book_name] [varchar](255) NULL, 

CONSTRAINT [PK_BOOK_EMBEDDED] PRIMARY KEY CLUSTERED 

(

[group_no] ASC, 

[row_id] ASC 

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

) ON [PRIMARY] 

=============================

組み込みキー

---------------------------

@Embeddable 

public class EmbeddedKey implements Serializable { 


    private static final long serialVersionUID = 1L; 



    @GeneratedValue(strategy = GenerationType.IDENTITY) 

    @Column(name = "row_id") 

    private Long rowId; 



    @Column(name = "group_no") 

    private int groupNo; 



    public Long getRowId() { 

     return rowId; 

    } 



    public void setRowId(Long rowId) { 

     this.rowId = rowId; 

    } 



    public static long getSerialversionuid() { 

     return serialVersionUID; 

    } 



    @Override 

    public int hashCode() { 

     final int prime = 31; 

     int result = 1; 

     result = (int) (prime * result + rowId); 

     result = prime * result + groupNo; 

     return result; 

    } 



    @Override 

    public boolean equals(Object obj) { 

     if (this == obj) 

      return true; 

     if (obj == null) 

      return false; 

     if (getClass() != obj.getClass()) 

      return false; 

     EmbeddedKey other = (EmbeddedKey) obj; 

     if (rowId != other.rowId) 

      return false; 

     if (groupNo != other.groupNo) 

      return false; 

     return true; 

    } 



    @Override 

    public String toString() { 

     return this.getRowId() + " " + this.getGroupNo() + " "; 

    } 



    public int getGroupNo() { 

     return groupNo; 

    } 



    public void setGroupNo(int groupNo) { 

     this.groupNo = groupNo; 

    } 



} 

エンティティ

--------------

@Entity(name = "BOOK_EMBEDDED") 

public class BookMySQL implements Serializable { 



    /** 

    * 

    */ 

    private static final long serialVersionUID = 1L; 



    @Column(name = "BOOK_NAME") 

    private String book_Name; 



    @EmbeddedId 

    private EmbeddedKey key; 



    public BookMySQL() { 

    } 



    public String getBook_Name() { 

     return book_Name; 

    } 



    public void setBook_Name(String book_Name) { 

     this.book_Name = book_Name; 

    } 



    public static long getSerialversionuid() { 

     return serialVersionUID; 

    } 



    public EmbeddedKey getKey() { 

     return key; 

    } 



    public void setKey(EmbeddedKey key) { 

     this.key = key; 

    } 



    @Override 

    public String toString() { 

     return this.getKey().toString() + " " + this.getBook_Name(); 

    } 



} 

エンティティマネージャクラス

-------- ----------------------

public class LocalEntityManager { 

    private static EntityManagerFactory emf; 

    private static EntityManager em; 



    private LocalEntityManager() { 

    } 



    public static EntityManager getEntityManger() { 

     if (emf == null) { 

      synchronized (LocalEntityManager.class) { 

       if (emf == null) { 

        emf = Persistence.createEntityManagerFactory("BookEntities"); 

        em = emf.createEntityManager(); 

       } 

      } 

     } 

     return em; 

    } 

} 

帳サービス

------------------

public class MySQLBookService { 



    public Long persistBook(String bookName) { 

     EmbeddedKey key = new EmbeddedKey(); 

     key.setGroupNo(1); 



     BookMySQL book = new BookMySQL(); 

     book.setBook_Name(bookName); 

     book.setKey(key); 



     EntityManager em = LocalEntityManager.getEntityManger(); 

     EntityTransaction tx = em.getTransaction(); 

     tx.begin(); 

     em.persist(book); 

     tx.commit(); 

     em.close(); 



     return book.getKey().getRowId(); 

    } 



    public BookMySQL findBook(int bookId) { 

     EntityManager em = LocalEntityManager.getEntityManger(); 

     EmbeddedKey key = new EmbeddedKey(); 

     key.setGroupNo(1); 

     key.setRowId(1L); 

     BookMySQL bookMySQL = em.find(BookMySQL.class, key); 

     System.out.println(bookMySQL); 

     return bookMySQL; 

    } 



    public static void main(String... args) { 

     MySQLBookService bookService = new MySQLBookService(); 

     // bookService.findBook(1); 



     bookService.persistBook("Lord of the rings"); 

    } 



} 

問題は、私はシーケンスを使用することはできませんし、常にこの findBookを実行することによって、エラーが発生しても失敗します。

ERROR: Cannot insert explicit value for identity column in table 'BOOK_EMBEDDED' when IDENTITY_INSERT is set to OFF. 

ご協力いただければ幸いです。

+0

SO規則に従ったYoy形式のコードはありますか? –

答えて

2

私はこの質問を言っていたので、私はan in-depth article about itを書くことにしました。

これを有効にする唯一の方法は、SQLInsertを上書きし、識別子列を設定することを期待するHibernateを騙すことです。代わりに、この変更に伴い

@Entity(name = "BOOK_EMBEDDED") 
@SQLInsert(sql = "insert into BOOK_EMBEDDED (BOOK_NAME, group_no, version) values (?, ?, ?)") 
public static class Book implements Serializable { 

    @EmbeddedId 
    private EmbeddedKey key; 

    @Column(name = "BOOK_NAME") 
    private String bookName; 

    @Version 
    @Column(insertable = false) 
    private Integer version; 

    public EmbeddedKey getKey() { 
     return key; 
    } 

    public void setKey(EmbeddedKey key) { 
     this.key = key; 
    } 

    public String getBookName() { 
     return bookName; 
    } 

    public void setBookName(String bookName) { 
     this.bookName = bookName; 
    } 
} 

を、あなたは次のテストを実行します:これは、代わりにnullにrowIdを設定するので、あなたの代わりにバージョンを設定し、そのよう独自のカスタムINSERT文を提供する場合に行うことができます

doInJPA(entityManager -> { 

    EmbeddedKey key = new EmbeddedKey(); 
    key.setGroupNo(1); 

    Book book = new Book(); 
    book.setBookName("High-Performance Java Persistence"); 

    book.setKey(key); 

    entityManager.persist(book); 
}); 

doInJPA(entityManager -> { 
    EmbeddedKey key = new EmbeddedKey(); 

    key.setGroupNo(1); 
    key.setRowId(1L); 

    Book book = entityManager.find(Book.class, key); 
    assertEquals("High-Performance Java Persistence", book.getBookName()); 
}); 

そして、Hibernateは右のSQL文を生成します。

Query:["insert into BOOK_EMBEDDED (BOOK_NAME, group_no, version) values (?, ?, ?)"], Params:[(High-Performance Java Persistence, 1, NULL(BIGINT))] 

Query:["select compositei0_.group_no as group_no1_0_0_, compositei0_.row_id as row_id2_0_0_, compositei0_.BOOK_NAME as BOOK_NAM3_0_0_, compositei0_.version as version4_0_0_ from BOOK_EMBEDDED compositei0_ where compositei0_.group_no=? and compositei0_.row_id=?"], Params:[(1, 1)] 

テストはGitHubで利用可能です。

1

有効にするには、identity_insertをONに設定する必要があります。

チェックこの記事を - How to set IDENTITY_INSERT

ので、コマンドの下に実行します。

SET IDENTITY_INSERT BOOK_EMBEDDED ON 
関連する問題