rob*_*del 6 spring hibernate jpa spring-data spring-data-jpa
我使用 spring boot 2,我的一些实体有复合键
当我尝试保存实体时,出现此错误
无法转换请求元素:org.springframework.beans.ConversionNotSupportedException:无法将“java.lang.Integer”类型的属性值转换为属性“sampling”所需的类型“com.lcm.model.SamplingsPK”;嵌套异常是 java.lang.IllegalStateException:无法将“java.lang.Integer”类型的值转换为属性“采样”所需的类型“com.lcm.model.SamplingsPK”:找不到匹配的编辑器或转换策略
我用那个方法得到我的实体
public Samples findById(Integer id, int year, String sampleLetter) {
Optional<Samples> optSamples = samplesRepository.findById(new SamplesPK(new SamplingsPK(year, id), sampleLetter));
if (optSamples.isPresent()) {
return optSamples.get();
}
return null;
}
Samples samples = samplesService.findById(idSeq, year, samplesLetter);
Compressions compressionTest = null;
if (samples.getTestSamples().getAbsorptionTest() != null) {
compressionTest = samples.getTestSamples().getCompressionTest();
} else {
compressionTest = new Compressions();
}
samplesService.save(samples);
Run Code Online (Sandbox Code Playgroud)
我的实体
@Entity
@IdClass(SamplesPK.class)
public class Samples extends BaseEntity{
@Id
private String sampleLetter;
@Embedded
private TestSamples testSamples;
@Id
@ManyToOne(optional=false)
@JoinColumns({
@JoinColumn(name = "sampling_id", referencedColumnName = "id"),
@JoinColumn(name = "sampling_year", referencedColumnName = "year")})
private Samplings sampling;
}
@Entity
@IdClass(SamplingsPK.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Samplings {
@Id
private Integer year;
@Id
@GeneratedValue
private Integer id;
@OneToMany(mappedBy = "sampling", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Samples> samples = new ArrayList<>();
}
public class SamplingsPK implements Serializable {
private int year;
private Integer id;
public SamplingsPK(int year, Integer id) {
this.id = id;
this.year = year;
}
}
public class SamplesPK implements Serializable {
private SamplingsPK sampling;
private String sampleLetter;
public SamplesPK(SamplingsPK sampling, String sampleLetter) {
this.sampling = sampling;
this.sampleLetter = sampleLetter;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
保存样本没问题,当我从采样中通过时
问题是,由于 ID 是手动设置的,并且这些实体没有@Version
属性,因此 Spring Data 没有好的方法来知道该实体是全新的实体还是现有的实体。在这种情况下,它决定它是一个现有实体并尝试 amerge
而不是 a persist
。这显然是一个错误的结论。
您可以在此处阅读有关 Spring Data 如何决定实体是否是新实体的更多信息。
我发现的最好的解决方案是始终让具有手动设置 ID 的实体类实现Persistable 接口。这解决了问题。对于任何此类情况,我都为自己制定了这条规则。大多数时候我不必实现,Persistable
因为我的实体要么有自动生成的密钥,要么我的实体使用“@Version”注释。但这是特殊情况。
因此,根据 Spring 官方文档中的建议,该类Samplings
将变为:
@Entity
@IdClass(SamplingsPK.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Samplings implements Persistable<SamplingsPK> {
@Transient
private boolean isNew = true;
@Id
private Integer year;
@Id
@GeneratedValue
private Integer id;
@OneToMany(mappedBy = "sampling", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Samples> samples = new ArrayList<>();
@Override
public boolean isNew() {
return isNew;
}
@PrePersist
@PostLoad
void markNotNew() {
this.isNew = false;
}
@Override
public SamplingsPK getId() {
return new SamplingsPK(year, id);
}
}
Run Code Online (Sandbox Code Playgroud)
此问题在https://jira.spring.io/browse/DATAJPA-1391@Id @ManyToOne
上进行跟踪,并且与Samples
. 作为一种解决方法,您可以尝试创建一个构造函数,Samplings
该构造函数接受两个主键,或者一个接受java.lang.Integer
? 这对于单个级别的复合主键有效,但如果您有多个级别,则可能不起作用。
您还year
输入了SamplingsPK
anint
而不是Integer
。这可能会导致 PK 识别出现问题,因为需要特别考虑来处理可自动装箱的基元类,而且我怀疑是否考虑过这一点。
归档时间: |
|
查看次数: |
673 次 |
最近记录: |