外键和引用类如何在 Hibernate 实体中一起存在?

Posted

技术标签:

【中文标题】外键和引用类如何在 Hibernate 实体中一起存在?【英文标题】:How can foreign key and reference class live together in a Hibernate entity? 【发布时间】:2014-06-05 02:34:57 【问题描述】:

我正在使用生成工具生成 Hibernate 实体,我收到如下错误:

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: model.PayLogEntity column: brank_card_id (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:676)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:698)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:720)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:474)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1362)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1865)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:860)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:779)
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:188)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    ... 67 more

抛出错误的类如下:

package model;

import javax.persistence.*;
import java.sql.Timestamp;

/**
 * Created by shenshijun on 14-6-5.
 */
@Entity
@Table(name = "pay_log", schema = "", catalog = "healthclube")
public class PayLogEntity 
    private int id;
    private Integer userId;
    private String brankCardId;
    private String payType;
    private Timestamp payTime;
    private Double count;
    private String message;
    private BankCardEntity bankCardByBrankCardId;

    @Id
    @Column(name = "id")
    public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    

    @Basic
    @Column(name = "user_id")
    public Integer getUserId() 
        return userId;
    

    public void setUserId(Integer userId) 
        this.userId = userId;
    

    @Basic
    @Column(name = "brank_card_id")
    public String getBrankCardId() 
        return brankCardId;
    

    public void setBrankCardId(String brankCardId) 
        this.brankCardId = brankCardId;
    

    @Basic
    @Column(name = "pay_type")
    public String getPayType() 
        return payType;
    

    public void setPayType(String payType) 
        this.payType = payType;
    

    @Basic
    @Column(name = "pay_time")
    public Timestamp getPayTime() 
        return payTime;
    

    public void setPayTime(Timestamp payTime) 
        this.payTime = payTime;
    

    @Basic
    @Column(name = "count")
    public Double getCount() 
        return count;
    

    public void setCount(Double count) 
        this.count = count;
    

    @Basic
    @Column(name = "message")
    public String getMessage() 
        return message;
    

    public void setMessage(String message) 
        this.message = message;
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        PayLogEntity that = (PayLogEntity) o;

        if (id != that.id) return false;
        if (brankCardId != null ? !brankCardId.equals(that.brankCardId) : that.brankCardId != null) return false;
        if (count != null ? !count.equals(that.count) : that.count != null) return false;
        if (message != null ? !message.equals(that.message) : that.message != null) return false;
        if (payTime != null ? !payTime.equals(that.payTime) : that.payTime != null) return false;
        if (payType != null ? !payType.equals(that.payType) : that.payType != null) return false;
        if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;

        return true;
    

    @Override
    public int hashCode() 
        int result = id;
        result = 31 * result + (userId != null ? userId.hashCode() : 0);
        result = 31 * result + (brankCardId != null ? brankCardId.hashCode() : 0);
        result = 31 * result + (payType != null ? payType.hashCode() : 0);
        result = 31 * result + (payTime != null ? payTime.hashCode() : 0);
        result = 31 * result + (count != null ? count.hashCode() : 0);
        result = 31 * result + (message != null ? message.hashCode() : 0);
        return result;
    

    @ManyToOne
    @JoinColumn(name = "brank_card_id", referencedColumnName = "id")
    public BankCardEntity getBankCardByBrankCardId() 
        return bankCardByBrankCardId;
    

    public void setBankCardByBrankCardId(BankCardEntity bankCardByBrankCardId) 
        this.bankCardByBrankCardId = bankCardByBrankCardId;
    

看来实体中的brank_card_id有两次beaning映射,一次是getBrankCardId,另一次是getBankCardByBrankCardId。所以我的问题是如何更改代码以消除冲突?

【问题讨论】:

其实我发现了一个类似的问题link 会有所帮助。 【参考方案1】:

Hibernate 的意思是您在此表中定义了 2 列,名称为 brank_card_id。一种是:

@Basic
@Column(name = "brank_card_id")
public String getBrankCardId() 
    return brankCardId;

另一个是:

@ManyToOne
@JoinColumn(name = "brank_card_id", referencedColumnName = "id")
public BankCardEntity getBankCardByBrankCardId() 
    return bankCardByBrankCardId;

@JoinColumn注解的name属性是外键列的实际名称。

您不能有 2 个名为 brank_card_id 的列。不要将您的加入列称为brank_card_id,而是将其称为其他名称,例如bank_card_fk。任何事情都应该有效。只需确保在关系的另一端正确引用它即可。

更改@JoinColumn 注释以匹配以下内容:

@ManyToOne
@JoinColumn(name = "bank_card_fk", referencedColumnName = "id")
public BankCardEntity getBankCardByBrankCardId() 
    return bankCardByBrankCardId;

【讨论】:

@JoinColumn(name = "brank_card_id", referencedColumnName = "id")。您不能将名称更改为brank_card_idbrank_card_pk,因为brank_card_id 映射到表中的列,而brank_card_pk 甚至不存在于表中。 我明白了你的想法,但我认为这不是一个好主意。因为您建议的更改使这一侧的映射无用,而在另一侧我有:@OneToMany(mappedBy = "userByUserId") public Collection<BankCardEntity> getBankCardsById() return bankCardsById; 。所以这些变化会使映射失败 但是您上面的@OneToMany 注释甚至不会指向PayLogEntity 对象和相应的表。它将指向BankCardEntity 对象和表。

以上是关于外键和引用类如何在 Hibernate 实体中一起存在?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA hibernate中删除表遇到主键被外键引用,违反完整约束条件,不能删除的问题 2张表,一张主表user,有

主键和外键的作用

Hibernate查询带有ID的外键字段

在休眠 ORM 中使用一个强制外键和一个可选外键中的列

随机森林分类如何在幕后工作?

做java项目时的主键和外键是啥啊?