在查询中获取但未包含在结果中的对象

时间:2018-08-10 14:15:48

标签: hibernate jpa spring-data-jpa

我使用spring数据jpa,休眠时我有一个复杂的结构。我搜索以获取带有某些对象的样本

Option Explicit
Sub searchPrefix()
Sheets("PREFIXES").Select
Dim CellCntnt As String
Dim tmpSrch As String
Dim isFound As Boolean
    isFound = False
Dim QtySrchChar As Integer
    QtySrchChar = 4
Dim Cnt As Integer
    Cnt = 0
Dim Tag As Integer

Cells.Range("A1").Select
Do Until IsEmpty(ActiveCell)
  Cnt = Cnt + 1
  ActiveCell.Offset(1, 0).Select
Loop
For Tag = 1 To Cnt - 1
CellCntnt = Cells(1 + i, 1).Value
tmpSrch = Left(CellCntnt, QtySrchChar)
    Cells.Range("G1").Select
    Do Until IsEmpty(ActiveCell)
        If Left(ActiveCell.Value, QtySrchChar) = tmpSrch Then
            QtySrchChar = QtySrchChar + 1
            tmpSrch = Left(CellCntnt, QtySrchChar)
            isFound = True
            MsgBox ("True Tags introduced with Std.Prefix  " & tmpSrch)
        End If
        If isFound Then
            isFound = False
            MsgBox ("False Tags introduced with Std.Prefix  " & tmpSrch)
            Cells.Range("G1").Select
        Else
                ActiveCell.Offset(1, 0).Select
        End If
    Loop
Next Tag
End Sub

当我保存新样本时,我会做

@Entity
@IdClass(SamplingsPK.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Samplings {

    @Id
    private int year;

    @Id
    @GeneratedValue
    private Integer sequenceId;

    @OneToOne
    private Products product;

    @OneToOne
    private Machines machine;

    @OneToOne
    private Dimensions dimension;

    @OneToOne
    private Colors color;

    @OneToMany(mappedBy = "sampling", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Samples> samples = new ArrayList<>();
    ...

}

@Entity
@IdClass(SamplesPK.class)
public class Samples extends BaseEntity { 

    @Id
    private String sampleLetter;

    @Id
    @ManyToOne(optional = false)
    @JoinColumns({
        @JoinColumn(name = "sampling_id", referencedColumnName = "sequenceId"),
        @JoinColumn(name = "sampling_year", referencedColumnName = "year")})
    private Samplings sampling;

    @OneToOne(mappedBy = "sample", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    //@JoinColumns({
    //    @JoinColumn(name = "sampling_id", referencedColumnName = "sequenceId"),
    //    @JoinColumn(name = "sampling_year", referencedColumnName = "year")})
    private TestSamples testSamples;
    ...
}

public class SamplesPK implements Serializable {

    private SamplingsPK sampling;

    private String sampleLetter;

    public SamplesPK(SamplingsPK sampling, String sampleLetter) {
        this.sampling = sampling;
        this.sampleLetter = sampleLetter;
    }

    private SamplesPK() {

    }
}

@Entity
public class TestSamples {

    @Id
    @SequenceGenerator(name = "test_samples_id_seq", sequenceName = "test_samples_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "test_samples_id_seq")
    private Integer id;

    @OneToOne(fetch = FetchType.LAZY)
    private Samples sample;

    @OneToOne(mappedBy = "testSample", fetch = FetchType.LAZY)
    private Compressions compressionTest;

    @OneToOne(mappedBy = "testSample", fetch = FetchType.LAZY)
    private Durabilities durabilityTest;

    @OneToOne(mappedBy = "testSample", fetch = FetchType.LAZY)
    private Scalings scalingTest;

    @OneToOne(mappedBy = "testSample", fetch = FetchType.LAZY)
    private Granulometries granulometryTest;

    @OneToOne(fetch = FetchType.LAZY)
    private Absorptions absorptionTest;
    ...
}

保存后,如果尝试使用testSample获取样本,则运行此查询

Samplings sampling = new Samplings();
..
Samples sample = new Samples();
 ...
TestSamples testSamples = new TestSamples();
testSamples.setSample(sample);
..
sample.setTestSamples(testSamples);

samplings.addSample(sample);

samplings = samplingsRepository.save(sampling);

当我检查样本时,TestSamples始终为空

我发现一个非常糟糕的解决方法...

@Query(
        value = "select s from Samples s Join fetch s.sampling sp Left Join fetch sp.machine m Join fetch sp.product p Join  fetch p.productType pt Join Fetch s.testSamples",
        countQuery = "select count(s) from Samples s Join s.sampling sp Left Join  sp.machine m Join  sp.product p Join  p.productType Join s.testSamples")
public Page<Samples> findAllFullSample(Pageable pageable);

查询代码

Page<Samples> pageSamples = samplesRepository.findAllFullSample(pageable);
List<Samples> samples = pageSamples.getContent();
for (Samples sample : samples) {
    TestSamples testSample= testSamplesRepository.findSamplesWithFullProductAndCompressionTest(sample.getSampling().getSequenceId(),sample.getSampling().getYear(), sample.getSampleLetter());
    sample.setTestSamples(testSample);
}
return pageSamples;

那为什么当我从Sample中获取TestSample时为null

2 个答案:

答案 0 :(得分:0)

我认为您的映射不正确。

当我查看Samples类时,会看到:

 @OneToOne(mappedBy = "sample", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumns({
        @JoinColumn(name = "sampling_id", referencedColumnName = "sequenceId"),
        @JoinColumn(name = "sampling_year", referencedColumnName = "year")})
    private TestSamples testSamples;
    ...

这看起来像是采样映射中的复制过去。

您应该先检查映射是否正确。

您是否从映射生成表?如果是,请检查生成的表是否符合预期。

答案 1 :(得分:0)

不确定这是否是答案-我针对示例类和示例代码进行了尝试:

    Samplings sampling = new Samplings();
    sampling.setYear(2018);

    Samples sample = new Samples();
    sample.setSampling(sampling);
    sample.setSampleLetter("A");

    TestSamples testSamples = new TestSamples();
    testSamples.setSample(sample);

    sample.setTestSamples(testSamples);
    sampling.addSample(sample);

    sampling = samplingsRepository.save(sampling);

    EntityManager em = ...;
    em.flush();
    em.clear();

    Pageable pageable = Pageable.unpaged();
    Page<Samples> samples = repository.findAllFullSample(pageable);

    Samples firstSampleBack = samples.getContent().get(0);
    System.out
            .println("--> testSamples=" + firstSampleBack.getTestSamples());

这成功返回了相关的TestSamples:

--> testSamples=TestSamples [id=1]

该测试注释掉了这三个类别之外的其他所有类别,包括查询在内,我不知道是否还需要其他什么来重现您所看到的问题。

似乎最容易完整地发布该工作示例。也许这至少将提供一个可供比较的选择。

https://github.com/df789/samples-query

这是针对Spring Boot和H2内存数据库的,因此应该独立运行。例如。 mvn clean test足以看到上面的测试用例。

修改

要继续执行下面Robert的评论,经过一点调试,Hibernate似乎比较了@Entity上的类型和@IdClass上的匹配字段,并尝试以任何一种方式进行。可以在源here中找到此检查。

如果PK上的类型匹配,则使用NormalMappedIdentifierValueMarshaller来构造PK标识符值。如果不这样做,似乎会尽最大努力继续使用命名明确的IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller。似乎从那里开始,代码沿混合类型走了一条“不太麻烦的路”-显然可以进行保存,但是稍后会发现一些惊喜。