0
@Entity
public class DocumentConsolidated {
    @Id private UUID id;

    @OneToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "metadata_id")
    private DocumentMetadata documentMetadata;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "documentConsolidated")
    private DocumentConfiguration documentConfiguration;
}

@Entity
public class DocumentConfiguration {
    @Id private UUID id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private DocumentConsolidated documentConsolidated;
}

// Service code:
QDocumentConsolidated qDoc = QDocumentConsolidated.documentConsolidated;
(JPQLQueryFactory) queryFactory
        .select(Projections.fields(qDoc, /*qDoc.id, */qDoc.documentConfiguration, qDoc.documentMetadata))
        .from(qDoc)
        .innerJoin(qDoc.documentConfiguration)
        .fetch();

This is only going 2 ways:

  • with qDoc.id: id is present, documentConfiguration is null
  • without qDoc.id: id is null, documentConfiguration is present

Why?

What I already checked: Hibernate query is always bringing documentConfiguration fields when I run it in a Postgres client. Bot documentMetadata is present in both cases.

NicolaeS
  • 423
  • 2
  • 7
  • I'm thinking out loud here and may be well off the mark but here goes. The querydsl `Q` classes represent tables and have all the columns and their data-types mapped to Java data-types. So `QDocumentConsolidated` doesn't know about `QDocumentConfiguration` because `QDocumentConfiguration` has the FK to `QDocumentConsolidated`. And JPA isn't in the mix here, the `Q` files just have values, not complex objects. So the FK to `QDocumentConsolidated` will be a `NumberPath` not a `DocumentConsolidated` instance. Have you tried projecting into a Java bean that contains the fields that you need? – Robert Bain Dec 23 '20 at 23:26
  • Hey @RobertBain! Sorry for replying late. Not sure what you mean by bean mapping. If you mean `Projections.bean(...)` I already tested and `documentConfiguration` is still null. I suspect issue comes from some ID or data conflict when the query is created with `Projections`, and it doesn't know ho to get the data back. I managed to work around this by using simple entitites - see my answer. – NicolaeS Dec 29 '20 at 17:19

1 Answers1

0

Problem is not solved, but I worked around it by removing Projections from the mix:

// Service code:
QDocumentConsolidated qDoc = QDocumentConsolidated.documentConsolidated;
QDocumentConfiguration qCfg = qDoc.documentConfiguration;
QDocumentMetadata qMeta = qDoc.documentMetadata;

return queryFactory
        .select(qDoc, qCfg, qMeta) // <-- get rid of Projections
        .from(qDoc)
        .innerJoin(qCfg) // <-- manual join on Lazy entity (qMeta is auto-joined)
        .fetch().stream()
        .map(tuple -> { // <-- entity creation, similar with Projections.bean()
            DocumentConsolidated documentConsolidated = Objects.requireNonNull(tuple.get(qDoc));
            documentConsolidated.setDocumentMetadata(tuple.get(qMeta));
            documentConsolidated.setDocumentConfiguration(tuple.get(qCfg));
            return documentConsolidated;
        })
        .collect(Collectors.toList());
NicolaeS
  • 423
  • 2
  • 7