JPA LEFT JOIN FETCH вызывает несколько операторов выбора, когда child равен нулю - PullRequest
1 голос
/ 05 февраля 2020

Вот мой запрос:

 @Query("SELECT DISTINCT f FROM FlowNlp f LEFT JOIN FETCH f.flowSelection fs JOIN FETCH f.chatConversations cc " +
            "WHERE f.initialFlowTriggered IN( SELECT DISTINCT fd.name FROM FlowDefinition fd, FlowPermission fp WHERE fp.flowName = fd.name " +
            ") AND cc.flowStep = 'Run NLP'" +
            "AND f.created BETWEEN :start AND :end")
    List<FlowNlp> getFlowNlpBetween(@Param("start") Date start, @Param("end") Date end);

, а вот сущности:


FlowNlp. java

@Entity
@Table(name = "flow_nlp")
@Data
@TypeDef(name = "json", typeClass = JsonStringType.class)
@NoArgsConstructor
public class FlowNlp implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "PK")
    private int id;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "FLOW_SELECTION_KEY", referencedColumnName = "FLOW_SELECTION_KEY")
    @NotFound(action = NotFoundAction.IGNORE)
    private List<ChatConversation> chatConversations;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FLOW_SELECTION_KEY")
    @NotFound(action = NotFoundAction.IGNORE)
    private FlowSelection flowSelection;

    @Column(name = "NLP_TYPE")
    private String nlpType;

    @Column(name = "FLOW_MATCH_JSON")
    @Type(type = "json")
    private Object flowMatchJson;

    @Column(name = "MATCH_DESCRIPTION")
    private String matchDescription;

    @Column(name = "INITIAL_FLOW_TRIGGERED")
    private String initialFlowTriggered;

    @Column(name = "JOB_ID")
    private String jobId;

    @Column(name = "IS_USED")
    private Boolean isUsed;

    @Column(name = "IS_TAUGHT")
    private Boolean isTaught;

    @Column(name = "IS_PRIMARY")
    private Boolean isPrimary;

    @Column(name = "CREATETS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Column(name = "MODIFYTS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modified;
}

ChatConversation. java

@Entity
@Table(name = "chat_conversation")
@Data
public class ChatConversation implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "CHAT_CONVERSATION_PK")
    private int id;

    @Column(name = "FLOW_SELECTION_KEY")
    private String flowSelectionKey;

    @Column(name = "CHATTING_USER")
    private String chattingUser;

    @Column(name = "CHATTING_USERTYPE")
    private String chattingUserType;

    @Column(name = "BOT")
    private String bot;

    @Column(name = "CHAT_CLIENT")
    private String chatClient;

    @Column(name = "PHRASE")
    private String phrase;

    @Column(name = "FLOW_STEP")
    private String flowStep;

    @Column(name = "JOB_ID")
    private String jobId;

    @Column(name = "INBOUND")
    private Boolean inbound;

    @Column(name = "UU_RESPONSE_DELTA")
    private String uuResponseDelta;

    @Column(name = "UB_RESPONSE_DELTA")
    private String ubResponseDelta;

    @Column(name = "THREAD_LOCK")
    private String threadLock;

    @Column(name = "CREATETS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Column(name = "MODIFYTS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modified;
}

FlowSelection. java

@Entity
@Table(name = "flow_selection")
@Data
public class FlowSelection {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "FLOW_SELECTION_KEY")
    private String id;

    @Column(name = "FINAL_SELECTED_FLOW")
    private String finalSelectedFlow;

    @Column(name = "FINAL_SELECTED_DESCRIPTION")
    private String finalSelectedDescription;

    @Column(name = "CREATETS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Column(name = "MODIFYTS")
    @Temporal(TemporalType.TIMESTAMP)
    private Date modified;
}

Всякий раз, когда результат FlowNlp не имеет FlowSelection, создается впечатление, что Hibernate выполняет еще 5 идентичных запросов в FlowSelection. таблица:

2020-02-04 15:19:01.808 DEBUG 56820 --- [nio-8081-exec-1] org.hibernate.SQL                        : select flowselect0_.flow_selection_key as flow_sel1_12_0_, flowselect0_.createts as createts2_12_0_, flowselect0_.final_selected_description as final_se3_12_0_, flowselect0_.final_selected_flow as final_se4_12_0_, flowselect0_.modifyts as modifyts5_12_0_ from flow_selection flowselect0_ where flowselect0_.flow_selection_key=?
2020-02-04 15:19:01.810 TRACE 56820 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [1580844097880_TK82506_e6b17201db3acc14eab2fcfaae961914]
2020-02-04 15:19:01.859 DEBUG 56820 --- [nio-8081-exec-1] org.hibernate.SQL                        : select flowselect0_.flow_selection_key as flow_sel1_12_0_, flowselect0_.createts as createts2_12_0_, flowselect0_.final_selected_description as final_se3_12_0_, flowselect0_.final_selected_flow as final_se4_12_0_, flowselect0_.modifyts as modifyts5_12_0_ from flow_selection flowselect0_ where flowselect0_.flow_selection_key=?
2020-02-04 15:19:01.859 TRACE 56820 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [1580844097880_TK82506_e6b17201db3acc14eab2fcfaae961914]
2020-02-04 15:19:01.892 DEBUG 56820 --- [nio-8081-exec-1] org.hibernate.SQL                        : select flowselect0_.flow_selection_key as flow_sel1_12_0_, flowselect0_.createts as createts2_12_0_, flowselect0_.final_selected_description as final_se3_12_0_, flowselect0_.final_selected_flow as final_se4_12_0_, flowselect0_.modifyts as modifyts5_12_0_ from flow_selection flowselect0_ where flowselect0_.flow_selection_key=?
2020-02-04 15:19:01.893 TRACE 56820 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [1580844097880_TK82506_e6b17201db3acc14eab2fcfaae961914]
2020-02-04 15:19:01.920 DEBUG 56820 --- [nio-8081-exec-1] org.hibernate.SQL                        : select flowselect0_.flow_selection_key as flow_sel1_12_0_, flowselect0_.createts as createts2_12_0_, flowselect0_.final_selected_description as final_se3_12_0_, flowselect0_.final_selected_flow as final_se4_12_0_, flowselect0_.modifyts as modifyts5_12_0_ from flow_selection flowselect0_ where flowselect0_.flow_selection_key=?
2020-02-04 15:19:01.920 TRACE 56820 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [1580844097880_TK82506_e6b17201db3acc14eab2fcfaae961914]
2020-02-04 15:19:01.950 DEBUG 56820 --- [nio-8081-exec-1] org.hibernate.SQL                        : select flowselect0_.flow_selection_key as flow_sel1_12_0_, flowselect0_.createts as createts2_12_0_, flowselect0_.final_selected_description as final_se3_12_0_, flowselect0_.final_selected_flow as final_se4_12_0_, flowselect0_.modifyts as modifyts5_12_0_ from flow_selection flowselect0_ where flowselect0_.flow_selection_key=?
2020-02-04 15:19:01.950 TRACE 56820 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [1580844097880_TK82506_e6b17201db3acc14eab2fcfaae961914]

Это вызывает больше времени, чем ожидалось для запросов, когда возвращается много строк, в которых нет FlowSelection.

Я пытался просто сделать обычный JOIN FETCH, но это больше не возвращает строки, в которых есть нулевой FlowSelection. Что я могу сделать, чтобы получить те же результаты, что и я, но без всех дополнительных (ненужных?) Запросов?

...