我正在使用MS SQL服务器,Spring 3,Hibernate JPA 2.0。 我有四个表Level0,Level1,level2和Level3。 Level0的id为P0作为主键。 Level1有一个compsoite主键,P0从level0作为FK和P1。 Level2有一个复合键Level0.P0,Level1.P1和P2。等等。 表格定义如下。
CREATE TABLE Level0
(
P0 integer NOT NULL,
Level0_name varchar(50) NOT NULL,
PRIMARY KEY (P0)
);
CREATE TABLE Level1
(
P0 integer NOT NULL,
P1 varchar(10) NOT NULL,
Level1_Name varchar(60),
PRIMARY KEY (P0, P1)
);
ALTER TABLE Level1 ADD CONSTRAINT FK_Level1 FOREIGN KEY (P0) REFERENCES Level0(P0);
CREATE TABLE Level2
(
P0 integer NOT NULL,
P1 varchar(10) NOT NULL,
P2 varchar(10) NOT NULL,
Level2_Name varchar(20),
PRIMARY KEY (P0, P1, P2)
);
ALTER TABLE Level2 ADD CONSTRAINT FK_Level2
FOREIGN KEY (P0, P1) REFERENCES Level1(P0, P1);
CREATE TABLE Level3
(
P0 integer NOT NULL,
P1 varchar(10) NOT NULL,
P2 varchar(10) NOT NULL,
P3 varchar(10) NOT NULL,
Level3_Name varchar(20) NOT NULL,
PRIMARY KEY (P0, P1, P2, P3)
);
ALTER TABLE Level3 ADD CONSTRAINT FK_Level3
FOREIGN KEY (P0, P1, P2) REFERENCES Level2(P0, P1, P2);
我为每个表都有相应的Java类。所以Level0有Level1s的集合,Level1有Level2s的集合,依此类推。 Level3包含Level2对象,Level2包含Level1对象,依此类推。这是Level1和Level2的Java类。
@Entity
@Table(name="Level1")
public class Level1 extends DomainObject
{
private String p1;
private Level0 level0;
private String name;
private List<Level2> level2s = new ArrayList<Level2>();
@Id
@NotNull
@Column(name="P1")
public String getP1()
{
return(p1);
}
@NotNull
@ManyToOne(cascade={CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH})
@JoinColumn(name="P0",
referencedColumnName="P0")
public Level0 getLevel0()
{
return(level0);
}
}
----------------------------------------------------------
@Entity
@Table(name="Level2")
public class Level2 extends DomainObject
{
private String p2;
private Level1 level1;
private String name;
private List<Level3> level3s = new ArrayList<Level3>();
@Id
@NotNull
@Column(name="P2")
public String getP2()
{ return(p2);
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="P0", referencedColumnName="P0"),
@JoinColumn(name="P1", referencedColumnName="P1")
})
public Level1 getLevel1()
{ return(level1);
}
@NotNull
@Column(name="Level2_Name")
public String getName()
{ return(name);
}
@OneToMany(orphanRemoval=true,
cascade=CascadeType.ALL,
mappedBy="level2",
fetch = FetchType.LAZY)
public List<Level3> getLevel3s()
{
return(level3s);
}
}
Level0,Level1和Level2之间的这些关系很有效。代码工作正常。 当我添加Level3类时,它会抛出错误。以下是Level3的外观。
public class Level3 extends DomainObject
{
private String p3;
private Level2 level2;
private String name;
@Id
@NotNull
@Column(name="P3")
public String getP3()
{
return(p3);
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="P0", referencedColumnName="P0"),
@JoinColumn(name="P1", referencedColumnName="P1"),
@JoinColumn(name="P2", referencedColumnName="P2")
})
public Level2 getLevel2()
{
return(level2);
}
@NotNull
@Column(name="Level3_Name")
public String getName()
{
return(name);
}
}
我收到以下错误: 引起:org.hibernate.AnnotationException:referencedColumnNames(P0,P1,P2) 引用Level2的Level3.level2未映射到单个属性。
Level2有2个外键及其自己的字段,3表示复合主键。这很有效。但是Level3有3个外键。事实并非如此。
有人可以帮我吗?感谢。
答案 0 :(得分:0)
这可能有所帮助,但我不确定这是否是正确的方法:
我遇到了类似的情况,但是我的复合FK-s并没有与主键相关联,而是与逻辑唯一相关。我通过为关系的每个组件创建额外的字段来解决这个问题。
即。在你的情况下,在Level2你会添加
@Entity
@Table(name="Level2")
public class Level2 extends DomainObject
{
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="P0", referencedColumnName="P0", insertable=false, updatable=false)
private Level0 level0Dummy;
// getter setter...
}
有了这个,我的Hibernate能够解决复合关系而没有出现这个错误。
P.S。在我看来,您没有正确映射主要复合键(“复合主键使用嵌入式类作为主键表示”),请查看http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e2177