我在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")
)
以下是映射(删除了不必要的信息)
@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)
你能帮忙解决一下吗?
答案 0 :(得分: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错误:这是一个Hibernate错误。请参阅HHH-4284。
要解决此问题,由于FOOID
足以确保唯一性,因此解决方案是从所有者ID和@Id
注释中删除@IdClass
注释。
答案 1 :(得分:1)
你可以这样做......它应该有效 -
@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;
}
答案 2 :(得分:0)
您在FOO表中使用了复合主键。所以你应该尝试@EmbeddedId属性,你应该在BAR实体中需要两个列“OWNER_ID”和“FOO_ID”,它们与FOO实体连接。