【问题标题】:Hibernate: How to join two tables with one of it doesn't have an id?Hibernate:如何连接两个表,其中一个表没有 id?
【发布时间】:2014-09-30 04:05:21
【问题描述】:

我的两个表(在 SQL Server 中):

create table cluster (
    id bigint primary key identity(1,1),
    name varchar(100)
)

create table cluster_member (
    cluster_id bigint,
    member_name varchar(100)
)

表 cluster_member 没有 id。 cluster_id 列就像一个外键,引用集群表中的 id 列。

我使用 Hiberate Tools 生成了 2 个 @Entity 类和一个 @Embeddable 类。我添加了一些类变量和 @OneToMany 和 @ManyToOne 注释,试图加入这两个表。但我收到一条错误消息:

org.hibernate.MappingException: Foreign key (FK_hk6sas3oycvcljwbjar7p9ky3:cluster_member [cluster_id,member_name])) must have same number of columns as the referenced primary key (cluster [id])

错误信息很清楚。但我不知道如何解决它。请帮忙。

这是我的代码:

Cluster.java

@Entity
@Table(name = "cluster" )
public class Cluster implements java.io.Serializable {

    private long id;
    private String name;
    private Set<ClusterMember> members;

    @Id
    @Column(name = "id", unique = true, nullable = false)
    public long getId() {
            return this.id;
    }

    @Column(name = "name", length = 100)
    public String getName() {
            return this.name;
    }

    @OneToMany(mappedBy = "id")
    public Set<ClusterMember> getMembers() {
            return members;
    }
}

ClusterMember.java

@Entity
@Table(name = "cluster_member" )
public class ClusterMember implements java.io.Serializable {

    private ClusterMemberId id;
    private Cluster cluster;

    @EmbeddedId
    @AttributeOverrides({ @AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id")),
                    @AttributeOverride(name = "memberName", column = @Column(name = "member_name", length = 100)) })
    public ClusterMemberId getId() {
            return this.id;
    }

    @ManyToOne
    @JoinColumn(name = "cluster_id")
    public Cluster getCluster() {
            return cluster;
    }
}

ClusterMemberId.java

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

    private Long clusterId;
    private String memberName;

    @Column(name = "cluster_id")
    public Long getClusterId() {
            return this.clusterId;
    }

    @Column(name = "member_name", length = 100)
    public String getMemberName() {
            return this.memberName;
    }
}

主要功能

    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
            sessionFactory = new Configuration().configure().buildSessionFactory();
            Session session = sessionFactory.getCurrentSession();
            Transaction tx = session.beginTransaction();
            Criteria criteria = session.createCriteria("my.hibernate.table.Cluster");
            criteria.add(Restrictions.like("name", "%ABC%"));
            @SuppressWarnings("unchecked")
            List<Cluster> clusters = criteria.list();
            for (Cluster cluster: clusters) {
                    System.out.println(cluster.toString());
            }
            tx.commit();
            sessionFactory.close();
    }

hibernate.cfg.xml

             <mapping class="my.hibernate.table.Cluster" />
             <mapping class="my.hibernate.table.ClusterMember" />

【问题讨论】:

    标签: java sql hibernate jpa join


    【解决方案1】:

    尝试改变这个:

    @OneToMany(mappedBy = "id")
    public Set<ClusterMember> getMembers() {
            return members;
    }
    

    @OneToMany(mappedBy = "cluster")
    public Set<ClusterMember> getMembers() {
            return members;
    }
    

    并在关联的 ManyToOne 映射上将可插入/可更新添加为 false。

    @ManyToOne
    @JoinColumn(name = "cluster_id", insertable="false", updatable="false")
    public Cluster getCluster() {
            return cluster;
    }
    

    因为您对 ClusterMember.id 并不真正感兴趣,而是对链接回 Cluster 的 FK 感兴趣。

    在 Hibernate 中,您不能将同一列用于不同的映射。 “ClusterMember”已经为 @Id 属性使用了“cluster_id”,因此如果您打算使用 ManyToOne 关联,则需要指示 Hibernate 忽略为此所做的任何更改(应忽略插入和更新)。

    您也可以使用Hibernate's @MapsId annotation,用于具有备用关联映射的复合标识符。

    【讨论】:

    • 现在我得到一个不同的错误:线程“主”org.hibernate.MappingException 中的异常:实体映射中的重复列:ClusterMember 列:cluster_id(应该使用 insert="false" update= 映射“假”)
    • 我编辑了我的帖子。添加了main函数,还有我的hibernate.cfg.xml。
    • 也更新了我的回复。
    • 成功了!一点点变化是:应该是insertable=false,updatable=false。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多