2012-06-05 26 views
2

我在ORM类层次结构中的对象上有连接表的问题,其中连接列由于滞后数据库结构而不是基类的主键。 下面是表设计的例子:如何在非主键列上连接表?

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") 
) 

这里是映射(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") 
    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; 
} 

这失败的异常:

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) 

请你帮助解决方案?

回答

4

你不能映射双向关联的两倍。一侧必须被标记为许多侧面的逆使用mappedBy属性:

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

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

编辑

以上应该工作,但不因下列休眠错误:这是一个Hibernate的错误。请参阅HHH-4284

为了规避此问题,由于FOOID足以确保唯一性,因此解决方法是从所有者标识和@IdClass注释中删除@Id注释。

+1

之前尝试过,不工作:com.package.Bar.foo的referencedColumnNames(FOOID)引用com.package.Foo未映射到单个属性 – Dzmitry

+1

这是一个Hibernate的bug。请参阅https://hibernate.onjira.com/browse/HHH-4284。 OTOH,难道你不能简单地从所有者ID中删除@Id注释,因为FOOID足以确保唯一性? –

+0

从所有者ID中删除@ Id注释并删除@ IdClass是有效的,并非如预期的那样,但是以某种方式工作。你可以请发布是作为一个不同的答案,所以我可以接受它作为一个解决方案?非常感谢你 – Dzmitry

1

U可以做如下....它应该工作 -

@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(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    @JoinColumn(name = "FOOID",nullable=false) 
    @ForeignKey(name = "fk")  
    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", updatable = false, insertable = false, nullable=false) 
    private Foo foo; 
} 
+1

不工作,说: 从com.package.Bar引用com.package.Foo的外键具有错误的列数。应该是2 – Dzmitry

0

您在FOO表中使用了复合主键。因此,您应该尝试使用@EmbeddedId属性,并且您应该在BAR实体中与FOO实体连接时需要两列“OWNER_ID”和“FOO_ID”。

+0

我知道,但我不能更改数据库结构:( – Dzmitry