2011-08-16 45 views
1

所以我反從我的數據庫設計的一些表,當我嘗試到我的對象保存到數據庫,我得到了以下錯誤:如何使用註釋在Hibernate中表示覆合鍵?

初始SessionFactory的創建failed.org.hibernate.AnnotationException:外鍵闖民宅com.mycode 。com.mycode.Account中的塊具有錯誤的列號。應該是2 異常線程「main」 java.lang.ExceptionInInitializerError

域對象是塊裏面包含了一些帳戶對象:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "Block") 
public Set<EAccount> getAccounts() { 
    return this.Accounts; 
} 

帳戶具有標識和角色的組合鍵。這一直是建立在一個單獨的類別:

@Embeddable 
public class BlockAccountId implements java.io.Serializable { 

private long blockOid; 
private String accountRole; 

public BlockAccountId() { 
} 

public BlockAccountId(long blockOid, String accountRole) { 
    this.blockOid = blockOid; 
    this.accountRole = accountRole; 
} 

@Column(name = "BLOCK_OID", nullable = false) 
public long getBlockOid() { 
    return this.blockOid; 
} 

public void setBlockOid(long blockOid) { 
    this.blockOid = blockOid; 
} 

@Column(name = "ACCOUNT_ROLE", nullable = false, length = 10) 
public String getAccountRole() { 
    return this.accountRole; 
} 

public void setAccountRole(String accountRole) { 
    this.accountRole = accountRole; 
} 

所以我想知道的。我如何鏈接blockOid上的表格和帳戶,但仍確保帳戶表格同時具有blockOid和accountRole作爲組合鍵。

任何示例將不勝感激!

N.B這是一個塊(一)賬戶(許多)的關係。

謝謝

回答

4

最簡單的方法是直接將您的關聯放置在嵌入式ID組件中。

Hibernate reference documentation

例(只寫重要的getter()和setter())

@Entity 
public class Block { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="BLOCK_OID") 
    long blockOid; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "id.block", cascade=CascadeType.ALL) 
    Set<Account> accounts = new HashSet<Account>(); 
} 

@Entity 
public class Account { 

    @EmbeddedId BlockAccountId id; 

    public Account() 
    { 
     this.id = new BlockAccountId(); 
    } 

    public void setBlock(Block pBlock) {   
     this.id.setBlock(pBlock); 
    } 

    public Block getBlock() { 
     return this.id.getBlock(); 
    } 

    public String getAccountRole() {  
     return this.id.getAccountRole(); 
    } 

    public void setAccountRole(String accountRole) { 
     this.id.setAccountRole(accountRole); 
    } 
} 


@Embeddable 
public class BlockAccountId implements java.io.Serializable { 

    @ManyToOne(optional = false)  
    private Block block; 

    @Column(name = "ACCOUNT_ROLE", nullable = false, length = 10) 
    private String accountRole; 

    public BlockAccountId() { 

    } 

    //Implement equals and hashcode 
} 

對應的數據庫表是:

CREATE TABLE block (
    BLOCK_OID bigint(20) NOT NULL auto_increment, 
    PRIMARY KEY (`BLOCK_OID`) 
) 


CREATE TABLE account (
    ACCOUNT_ROLE varchar(10) NOT NULL, 
    block_BLOCK_OID bigint(20) NOT NULL, 
    PRIMARY KEY (`ACCOUNT_ROLE`,`block_BLOCK_OID`), 
    KEY `FK_block_OID` (`block_BLOCK_OID`), 
    CONSTRAINT `FK_block_OID` FOREIGN KEY (`block_BLOCK_OID`) REFERENCES `block` (`BLOCK_OID`) 
) 
+0

感謝。我原本有這個,但在Block對象中有一個額外的@id。然後錯誤消息把我扔了,讓我覺得這是AccountId類(嵌入式組合ID)。看起來你必須看看hibernate如何反向工程師的事情。謝謝你的回答 – Mick

+1

沒問題!!! –

+0

很棒的回答。只需要提到對於沒有任何約束的普通組合鍵,將@Id註釋添加到每個getter方法中作爲組合鍵一部分的字段足以滿足Hibernate,因此它不會抱怨類文件不會如何「在實際查詢數據庫之後反映數據庫元數據。當然,如果有任何[如:ManyToOne(...)等],你可以並且應該指定其他關係,但是如果你擁有的只是一個組合鍵,並且希望讓Hibernate讓你獨處,這應該就夠了。 –

0

基於Hibernate文檔,這裏的link

根據它您可以執行以下操作:

@Entity 公共類賬戶{

@EmbeddedId BlockAccountId id; 

@MapsId(value = "blockOid") 
@ManyToOne 
private Block block; 

public Account() 
{ 
    this.id = new BlockAccountId(); 
} 

public void setBlock(Block pBlock) {   
    this.block = pBlock; 
} 

public Block getBlock() { 
    return this.block; 
} 

public String getAccountRole() {  
    return this.id.getAccountRole(); 
} 

public void setAccountRole(String accountRole) { 
    this.id.setAccountRole(accountRole); 
} 

}