2011-08-16 12 views
1

私は次のエラーを取得するデシベルに私のオブジェクトを保存しようとすると、だから私は私のDBからいくつかのテーブルを設計しそしてリバース:注釈を使用してHibernateで複合キーを表現する方法?

初期のSessionFactory作成failed.org.hibernate.AnnotationException:外部キー参照元のcom.mycodeをcom.mycode.Accountの.Blockのカラム数が正しくありません。スレッド内の2 例外である必要があり、「メイン」java.lang.ExceptionInInitializerError

ドメインオブジェクトは、アカウントオブジェクトの数を含むブロックです:

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

アカウントは、IDおよびロールの複合キーを持っています。これは個別のクラスでセットアップされています:

@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これはブロック(1つ)からアカウント(複数)の関係です。

おかげ

答えて

4

最も簡単に埋め込まれたIDコンポーネントに直接関連付けを配置することです。

Hibernate reference documentation

例(唯一の重要なゲッターを(書き込み)とセッター())

@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 
} 

対応するデータベース・テーブルには、次のとおりです。Hibernateのドキュメントに基づいて

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)だと思うようにしました。あなたはどのように冬眠リバースエンジニアのものを見なければならないように見えます。合意の答えをありがとう – Mick

+1

問題はありません! –

+0

すばらしい答え。コンストレインを持たない通常のコンポジットキーでは、コンポジットキーの一部であるフィールドの各ゲッターメソッドに@Idアノテーションを追加するだけでHibernateを満足させることができますので、クラスファイルがどのようにして '実際にデータベースに照会した後にデータベースのメタデータを反映します。もちろん、他のリレーションシップを指定することもできます(例:ManyToOne(...)など)。ただし、すべてがコンポジットキーで、Hibernateにあなたを残したい場合は、それは十分であるはずです。 –

0

はここ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); 
} 

}このため

関連する問題