Hibernate:如何用其中一个表连接两个表没有id?

时间:2014-08-07 03:27:20

标签: java sql hibernate jpa join

我的两个表(在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" />

1 个答案:

答案 0 :(得分:2)

尝试更改此内容:

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

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

并在关联的ManyToOne映射上将insertable / updatable添加为false。

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

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

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

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