【问题标题】:How to Represent Composite keys in Hibernate using Annotations?如何使用注释在 Hibernate 中表示复合键?
【发布时间】:2011-10-28 04:18:44
【问题描述】:

所以我从我的数据库中反向工程了一些表,当我尝试将我的对象保存到数据库时,我收到以下错误:

初始 SessionFactory 创建 failed.org.hibernate.AnnotationException:从 com.mycode.Account 引用 com.mycode.Block 的外键具有错误的列数。应该是 2 线程“主”java.lang.ExceptionInInitializerError 中的异常

域对象是包含许多帐户对象的块:

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

Account 有一个 Id 和 Role 的组合键。这已在单独的类中设置:

@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 上链接表 Block 和 account 但仍确保 account 表同时具有 blockOid 和 accountRole 作为复合键。

任何示例将不胜感激!

注意,这是块(一)到帐户(多)的关系。

谢谢

【问题讨论】:

    标签: java hibernate persistence


    【解决方案1】:

    最简单的方法是将您的关联直接放在嵌入的 id 组件中。

    Hibernate 参考文档

    示例(只写重要的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`)
    )
    

    【讨论】:

    • 谢谢。实际上我最初有这个但在 Block 对象中有一个额外的@id。然后错误消息把我吓跑了,让我认为它是 AccountId 类(嵌入的复合 id)。看起来你必须看看hibernate是如何逆向工程的。感谢您的简洁回答
    • 很好的答案。只想提一下,对于没有任何约束的普通复合键,为作为复合键一部分的字段的每个 getter 方法添加 @Id 注释足以满足 Hibernate,因此它不会抱怨类文件如何不t 在实际查询数据库后反映数据库元数据。当然,如果有任何关系[例如:ManyToOne(...) 等],您可以并且应该指定其他关系,但是如果您只有一个复合键并且想让 Hibernate 让您独自一人,这应该足够了。
    【解决方案2】:

    基于休眠文档,这里是link

    在此基础上,您可以执行以下操作:

    @实体 公共类帐户{

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

    }

    【讨论】:

      猜你喜欢
      • 2013-11-25
      • 2011-02-22
      • 2023-04-01
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      相关资源
      最近更新 更多