2013-04-09 44 views
2

我的實體有兩個外鍵,其中一個是主鍵。我在JPA Wiki中讀到,如果孩子的(採購)主鍵與父母的(文章)主鍵相同,則建立@OneToOne關係。Hibernate尋找錯誤的主鍵

@SuppressWarnings("serial") 
@Entity 
public class Procurement implements Serializable { 

    @Id 
    @OneToOne 
    // the child's primary key is the same as the parent 
    @JoinColumn(name = "articleId", referencedColumnName = "id") 
    private Article article; 

    @OneToOne 
    @JoinColumn(name = "supplierId", referencedColumnName = "id") 
    private Supplier supplier; 

遵循這一標準的做法,在JpaRepository應該是這樣的:

@Repository 
public interface IProcurementRepository extends 
     JpaRepository<Procurement, Article> 

但是,如果我要撥打的findOne-方法(查找主鍵)提供的「條」對象,Hibernate會拋出一個異常。

org.hibernate.TypeMismatchException:提供了錯誤類型的ID爲 類de.willms.spring.myerp.model.Procurement。預計:類 de.willms.spring.myerp.model.Procurement,得到了類 de.willms.spring.myerp.model.Article

數據庫表結構:

表「的文章「(ID,shortText)

表 」供應商「(ID,姓名)

表 」採購「(條款ArticleID,供應商ID,價格)

我需要更改哪些內容才能找到相應的「Article」對象的「採購」記錄?

+0

你的問題是有點混亂。你說**採購**是孩子,**第**條是父母,但採購不是從條款延伸。而且這是一個有點怪異,你有兩個**標識**和** ** OneToOne註解的同時東西。 ** Id **表示一個數據列(或者如果使用複合鍵則爲列)而** OneToOne **實際上是兩個表之間的關係。你能否提供你的數據庫表結構來讓人們幫助你? – spiritwalker 2013-04-09 09:02:25

回答

1

最後,我在Hibernate中找到了一個特殊的函數(令人驚訝,但在文檔中難以理解)導致了一個解決方案。

只要主鍵由多個列組成,或者就像我的情況一樣,與其他表相關,就必須編寫一個特殊的ID類。

@Embeddable  
public class Procurement_ID implements Serializable { 

    /** 
    * This attribute establishes the 1:1 connection to a record in the 
    * "article" table. The column "articleId" is a foreign key to the column 
    * "id" in the {@link Article} entity. (Warning: This is Hibernate 
    * specific!) 
    */ 
    @OneToOne 
    @JoinColumn(name = "articleId", referencedColumnName = "id") 
    private Article article; 

    /** 
    * This attribute establishes the 1:1 connection to a record in the table 
    * "supplier". The column "supplierId" is a foreign key to the column "id" 
    * in the {@link Supplier} entity. (Warning: This is Hibernate specific!) 
    */ 
    @OneToOne 
    @JoinColumn(name = "supplierId", referencedColumnName = "id") 
    private Supplier supplier; 

(由於更「歸一化」的數據模型,我切換到複合主鍵。)

由於@Embeddable註釋的,該ID可以被注射到實體類。

@Entity 
public class Procurement implements Serializable { 

    /** 
    * The composite primary key of the underlying table is defined in the 
    * {@link Procurement_ID} class. 
    */ 
    @EmbeddedId 
    private Procurement_ID procid; 

跟我使用這種方法時,Hibernate插入正外鍵檢查一個新的記錄:

[DEBUG] 生成的標識:成分[文章,供應商] {文章= de.willms .spring.myerp.model.Article#1,supplier = de.willms.spring.myerp.model.Supplier#1},using strategy:org.hibernate.id。CompositeNestedGeneratedValueGenerator

...(Flusing)...

[調試]清單實體:... de.willms.spring.myerp.model.Procurement {價格= 2.5,交貨期= 10, procid = component [article,supplier] {article = de.willms.spring.myerp.model.Article#1, supplier = de.willms.spring.myerp.model.Supplier#1},priceUnit = $}

然而,很可惜的是,JpaRepository不能注入查找() - 方法存根concering古板的只是其中的一部分ary鍵。它「無法解析路徑上的屬性」。歡迎您發表評論!

1

您仍然必須使用int或long類型的id。區別在於,您不得不使用@JoinColumn加入@PrimaryKeyJoinColumn。你的課應該是這樣的。

@SuppressWarnings("serial") 
@Entity 
public class Procurement implements Serializable { 

    @Id 
    @GeneratedValue(generator = "articleForeignGenerator") 
    /* Hibernate-specific generator needed for shared primary key */ 
    @GenericGenerator(name = "articleForeignGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "article")) 
    @Column(name = "articleId") 
    private int articleId; 

    @OneToOne 
    // the child's primary key is the same as the parent 
    @PrimaryKeyJoinColumn 
    private Article article; 

    @OneToOne 
    @JoinColumn(name = "supplierId", referencedColumnName = "id") 
    private Supplier supplier; 

請注意,我使用特定於hibernate的生成器生成ID。您的JPA提供商可能會有所不同。

+0

很抱歉,但你的解決方案會導致另一個異常: 「org.hibernate.id.IdentifierGenerationException:試圖從空一到一個屬性[de.willms.spring.myerp.model.Procurement.article]分配ID」。我希望在Hibernate文檔中找到一些方法。 – PWillms 2013-04-09 14:32:39

+0

@PWillms您確定每次採購都有一篇文章嗎? – WilQu 2013-04-09 14:35:57

+0

是的,從一元級別看到,我想存儲有關現有項目的採購數據。具體記錄應該連接到供應商記錄。 – PWillms 2013-04-09 15:07:03