既存のデータベース (今のところ変更できません) を 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
埋め込み fk に注釈付きの名前付き列がない@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;
}