Объект получен в запросе, но не включен в результат

Я использую данные spring jpa, спящий режим у меня сложная структура. Я ищу образцы с извлеченным объектом

@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;
    ...
}

Когда я сохраняю новые образцы, я делаю

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);

После сохранения, если я попытаюсь получить образцы с помощью testSample, я запускаю этот запрос

@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);

Когда я проверяю образец, TestSamples всегда имеет значение null

Я нашел очень плохой обходной путь ...

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;

Код запроса

@Query(value = "select ts from TestSamples ts Join ts.sample s left Join Fetch ts.compressionTest where s.sequenceId=:id and s.year=:year and s.sampleLetter=:sampleLetter")
public TestSamples findSamplesWithFullProductAndCompressionTest(@Param("id") Integer id, @Param("year") int year, @Param("sampleLetter") String sampleLetter);

Итак, почему TestSample имеет значение null, когда я получаю его из Sample

попробуйте с FetchType Eager на testSamples

pvpkiran 10.08.2018 16:18

Цель использования fetch = FetchType.LAZY в TestSamples в Samples - получить только то, что мне нужно на 99% ... поэтому я создал конкретный запрос: findAllFullSample

robert trudel 10.08.2018 16:37
0
2
82
2

Ответы 2

Я предполагаю, что ваше отображение неверно.

Когда я смотрю на класс 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;
    ...

Это похоже на копирование прошлого из отображения выборки.

Вы должны сначала проверить правильность отображения.

Вы генерируете таблицы из сопоставления? Если да, проверьте, выглядят ли сгенерированные таблицы ожидаемыми.

имея @JoinColumns или ничего не меняя, все генерируется из сопоставления, и все в порядке

robert trudel 10.08.2018 20:55

Не уверен, что это ответ как таковой - я пробовал это с примерами классов и примером кода:

    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 достаточно, чтобы увидеть тестовый пример выше.

Редактировать

В продолжение комментария Роберта ниже, после небольшой отладки, похоже, что Hibernate сравнивает типы на @Entity и соответствующие поля на своем @IdClass и пытается продолжить в любом случае. Эту проверку можно найти в источнике здесь.

Если типы в PK совпадают, для создания значения идентификатора PK используется NormalMappedIdentifierValueMarshaller. Если они этого не сделают, то, кажется, будет сделано все возможное, чтобы продолжить с выразительно названным IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller. Кажется, что оттуда код следует «менее проторенным» путем со смешанными типами - очевидно, что сохранение работает, но есть сюрпризы, которые можно найти позже.

интересно, попробовал ваш пример, после большего анализа, в SamplesPK вы используете Sampling вместо SamplingsPK. если вы используете SamplingsPK, у вас возникнет проблема. на самом деле, когда вы используете выборку, у вас не возникает никаких проблем, потому что вы знаете, что использовать класс, который расширяет выборку ...

robert trudel 14.08.2018 20:30

Хммм, хороший анализ. Беглый взгляд на код Hibernate подсказывает, что вы что-то знаете о типах внешнего ключа в SamplesPK. Я обновил ответ выше, добавив более подробную информацию о том, что происходит.

df778899 14.08.2018 23:32

я дал вам +100 ... это не решает проблему ... но вы предоставили хороший ответ и анализ ...

robert trudel 15.08.2018 13:35

Другие вопросы по теме