我想将现有数据库(我们现在无法更改)映射到 Hibernate 实体。但是我的映射似乎有一个我无法克服的传递映射复合键的问题。
FluidSampleLabel 将 FluidSample 作为外键并作为其自己的复合主键的一部分。Hibernate 似乎忽略了 FluidSampleLabel 中嵌入外键实体 FluidSample 映射的列/嵌入 id。
Github 上的测试项目: https ://github.com/burka/hibernate-transitive-compkey-problem.git
org.hibernate.AnnotationException: A Foreign key refering compkey_problem.model.FluidSample from compkey_problem.model.FluidSampleLabel has the wrong number of column. should be 1
如果嵌入式 fks 上没有@ManyToOne
带注释的命名列,我会收到以下错误:
Caused by: org.hibernate.MappingException: Foreign key (FK246FD874D0837E3B:fluid_sample_label [sample])) must have same number of columns as the referenced primary key (fluid_sample [sampleGroup,pre_post])
create sequence sample_group_seq start 10000;
create table sample_group (
sample_group_id int primary key,
payload varchar(200)
);
create table fluid_sample (
sample_group_id int not null,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
amount number(20,10) not null,
primary key ( sample_group_id, pre_post ),
constraint fk_fluid_sample_group foreign key ( sample_group_id ) references sample_group ( sample_group_id )
);
create table fluid_sample_label (
sample_group_id int,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
label varchar(200) not null,
primary key ( sample_group_id, pre_post, label ),
constraint fk_fluid_label_fluid foreign key ( sample_group_id, pre_post ) references fluid_sample ( sample_group_id, pre_post )
);
@Entity
@SequenceGenerator(name = "sampleGroupSequence", sequenceName = "sample_group_seq", allocationSize = 1)
@Table(name = "sample_group")
public class SampleGroup
{
@Id
@GeneratedValue(generator = "sampleGroupSequence", strategy = GenerationType.SEQUENCE)
@Column(name = "sample_group_id")
private Integer sampleGroupId;
@OneToMany(mappedBy = "sampleGroup")
private List<FluidSample> fluidSamples = new ArrayList<>();
@Column(name = "payload")
private String payload;
public SampleGroup()
{
}
public FluidSample addNewPreFluidSample()
{
FluidSample sample = new FluidSample(this, PrePost.PRE);
this.fluidSamples.add(sample);
return sample;
}
}
@Entity
@Table(name = "fluid_sample")
public class FluidSample
{
@Id
@ManyToOne
@JoinColumn(name = "sample_group_id")
private SampleGroup sampleGroup;
@Id
@Column(name = "pre_post")
@Enumerated(EnumType.STRING)
private PrePost prePost;
@OneToMany(mappedBy = "sample")
private List<FluidSampleLabel> labels = new ArrayList<>();
@Column(name = "amount")
private BigDecimal amount;
@SuppressWarnings("unused")
private FluidSample()
{
}
public FluidSample(SampleGroup sampleGroup, PrePost prePost)
{
this.sampleGroup = sampleGroup;
this.prePost = prePost;
}
public FluidSampleLabel addNewLabel(String value)
{
FluidSampleLabel label = new FluidSampleLabel(this, value);
this.labels.add(label);
return label;
}
}
@Entity
@Table(name = "fluid_sample_label")
public class FluidSampleLabel
{
@Id
@ManyToOne
@JoinColumns({ @JoinColumn(name = "sample_group_id"), @JoinColumn(name = "pre_post")})
private FluidSample sample;
@Id
private String value;
@SuppressWarnings("unused")
private FluidSampleLabel()
{
}
FluidSampleLabel(FluidSample sample, String value)
{
this.sample = sample;
this.value = value;
}
public String getValue()
{
return this.value;
}
}
public enum PrePost
{
PRE, POST;
}