如何在非主键列上连接表? [英] How do I join tables on non-primary key columns?

查看:268
本文介绍了如何在非主键列上连接表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于ORM类层次结构中的对象上的连接表,由于滞后数据库结构,连接列不是基类的主键,所以存在连接表的问题。
这里是一个表设计的例子:

pre code CREATE TABLESCH。FOO

OWNERIDNUMBER(10,0)NOT NULL ENABLE,
FOOIDNUMBER(10,0)NOT NULL ENABLE,
CONSTRAINTFOO_PKPRIMARY KEY(OWNERID, FOOID)
CONSTRAINTFOO_FK1FOREIGN KEY(OWNERID)REFERENCESSCH。OWNERS(OWNERID)ENABLE


CREATE TABLESCH 。BAR

BARIDNUMBER(10,0)NOT NULL ENABLE,
FOOIDNUMBER(10,0)
CONSTRAINTBAR_PKPRIMARY KEY (BARID)

这里是映射(删除了unesessary信息)

  @Entity 
@IdClass(FooId.class)
@Table(name =FOO)
public class Foo implements java.io.Serializable
{
@Id
@Column(name =OWNERID)
private BigInteger ownerId;

@Id
@SequenceGenerator(name =FOO_GENERATOR,sequenceName =SEQ_FOO)
@GeneratedValue(generator =FOO_GENERATOR)
@Column(name =FOOID)
私人BigInteger ID;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name =FOOID,referencedColumnName =FOOID)
@Fetch(value = FetchMode.SUBSELECT)
@Cascade(value = {CascadeType.ALL})
private Set< Bar> bar = new LinkedHashSet< Bar>(0);


$ b $实例
@Table(name =BAR)
public class Bar实现java.io.Serializable
{
@Id
@Column(name =BARID)
私人BigInteger ID;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =FOOID,referencedColumnName =FOOID)
private Foo foo;
}

这种情况会导致例外:

 引起:org.hibernate.AnnotationException:com.package.Bar.foo的referencedColumnNames(FOOID)引用com.package.Foo未映射到单个属性
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:204)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:114)
at org.hibernate.cfg。 Configuration.processEndOfQueue(Configuration.java:1580)
位于org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1503)
位于org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375)

您可以请求一个解决方案吗?

解决方案

您不能两次映射双向关联。一方必须使用 mappedBy 属性标记为Many方的逆向:

  @OneToMany(fetch = FetchType.LAZY,mappedBy =foo)
@Fetch(value = FetchMode.SUBSELECT)
@Cascade(value = {CascadeType.ALL})
私人设置< Bar> bar = new LinkedHashSet< Bar>(0);

...

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =FOOID,referencedColumnName =FOOID)
私人Foo foo;

没有任何理由告诉Hibernate两次该关联是由连接列FOOID映射的。这样做实际上是一个错误,因为它定义了两种不同的单向关联,而不是一种双向关联。



编辑



<上面应该可以工作,但不是由于下面的Hibernate bug:这是一个Hibernate的bug。请参阅 HHH-4284



为了避免这个问题,由于 FOOID 足以确保唯一性,所以解决方法是删除 @Id 注释来自所有者ID和 @IdClass 注释。


I have an issue with join tables on an object in an ORM class hierarchy where the join column is NOT the primary key of the base class due a lagacy database structure. Here is an example of the table design:

CREATE TABLE "SCH"."FOO"
(
        "OWNERID"       NUMBER(10,0) NOT NULL ENABLE,
        "FOOID"         NUMBER(10,0) NOT NULL ENABLE,
        CONSTRAINT "FOO_PK" PRIMARY KEY ("OWNERID", "FOOID")
        CONSTRAINT "FOO_FK1" FOREIGN KEY ("OWNERID") REFERENCES "SCH"."OWNERS" ("OWNERID") ENABLE
)

CREATE TABLE "SCH"."BAR"
(
        "BARID"             NUMBER(10,0) NOT NULL ENABLE,
        "FOOID"             NUMBER(10,0)
        CONSTRAINT "BAR_PK" PRIMARY KEY ("BARID")
)

And here are the mappings (unesessary infomation removed)

@Entity
@IdClass(FooId.class)
@Table(name = "FOO")
public class Foo implements java.io.Serializable
{
    @Id
    @Column(name = "OWNERID")
    private BigInteger ownerId;

    @Id
    @SequenceGenerator(name = "FOO_GENERATOR", sequenceName = "SEQ_FOO")
    @GeneratedValue(generator = "FOO_GENERATOR")
    @Column(name = "FOOID")
    private BigInteger id;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
    @Fetch(value = FetchMode.SUBSELECT)
    @Cascade(value = {CascadeType.ALL})
    private Set<Bar> bar = new LinkedHashSet<Bar>(0);
}


@Entity
@Table(name = "BAR")
public class Bar implements java.io.Serializable
{
    @Id
    @Column(name = "BARID")
    private BigInteger id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
    private Foo foo;
}

This fails with an exception:

Caused by: org.hibernate.AnnotationException: referencedColumnNames(FOOID) of com.package.Bar.foo referencing com.package.Foo not mapped to a single property
    at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:204)
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:114)
    at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1580)
    at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1503)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1419)
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375)

Could you please help with a solution?

解决方案

You must not map the bidirectional association twice. The One side must be marked as the inverse of the Many side, using the mappedBy attribute:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "foo")
@Fetch(value = FetchMode.SUBSELECT)
@Cascade(value = {CascadeType.ALL})
private Set<Bar> bar = new LinkedHashSet<Bar>(0);

...

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
private Foo foo;

There is no reason to tell Hibernate twice that the association is mapped by the join column FOOID. And doing it is actually an error, because it defines two different unidirectional associations rather than one bidirectional association.

EDIT

The above should work, but doesn't due to the following Hibernate bug: It's a Hibernate bug. See HHH-4284.

To circumvent this problem, since the FOOID is enough to ensure uniqueness, a solution would be to remove the @Id annotation from the owner ID and the @IdClass annotation.

这篇关于如何在非主键列上连接表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆