Hibernate создает два соединения с одной и той же таблицей

#java #spring #hibernate #jpa

#java #весна #спящий режим #jpa

Вопрос:

У меня есть три таблицы: ScanMeta, Scan и Batch.

 @Entity
@Table(name = "scan_meta_letter")
public class ScanMetaLetter {

    @Id
    @Column(name = "scan_meta_id")
    private Long id;

    @OneToOne(mappedBy = "scanMeta")
    @JoinColumn(name = "scan_id")
    private Scan scan;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;
   
    ....

}
  
 @Entity
@Table(name = "scan")
public class Scan {

    @Id
    @GeneratedValue
    @Column(name = "scan_id")
    private Long id;

    @Column(name = "read_date")
    private OffsetDateTime readDate;

    @Column(name = "deletion_date")
    private OffsetDateTime deletionDate;

    @Column(name = "type", length = 10)
    @Enumerated(EnumType.STRING)
    private ScanType type;

    @ManyToOne(fetch = FetchType.LAZY)
    private Batch batch;

    ....

}
  
 @Entity
@Table(name = "batch")
public class Batch {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "batch_status")
    @Enumerated(EnumType.STRING)
    private BatchStatus batchStatus;

    @Column(name = "batch_type", length = 10)
    @Enumerated(EnumType.STRING)
    private BatchType batchType;

    ....

}

  

Когда я создаю Specification<ScanMettaLetter> , я извлекаю таблицы: сканирование и пакет.

 Specification<ScanMetaLetter> s = Specification.where((root, criteriaQuery, criteriaBuilder) -> {
    criteriaQuery.distinct(true);
    root.fetch("scan", JoinType.LEFT).fetch("batch", JoinType.LEFT);
    return null;
});
  

Если я хотел бы, чтобы ответ сортировался по scan.type — все в порядке. Но если сортировать по — scan.batch.BatchStatus, я получаю сообщение об ошибке:

 could not prepare statement; SQL [select distinct scanmetale0_.scan_meta_id as scan_met1_7_0_, 
scan1_.scan_id as scan_id1_3_1_, batch2_.id as id1_0_2_, scanmetale0_.first_name as 
recipien3_9_0_, scanmetale0_.last_name as recipien5_9_0_, scan1_.batch_id as 
batch_i13_3_1_, scan1_.deletion_date as deletion3_3_1_, scan1_.read_date as read_dat8_3_1_, 
scan1_.type as type11_3_1_, batch2_.batch_status as batch_st3_0_2_, 
batch2_.batch_type as batch_ty4_0_2_ from 
scan_meta_letter scanmetale0_ left outer join scan scan1_ on 
scanmetale0_.scan_meta_id=scan1_.scan_id left outer join batch batch2_ on 
scan1_.batch_id=batch2_.id cross join batch batch6_ where scan1_.batch_id=batch6_.id and 
(scan1_.reg_code like ?) and scan1_.type=? and batch6_.batch_status=? and 1=1 order by 
batch6_.batch_status asc limit ?]; nested exception is 
org.hibernate.exception.SQLGrammarException: could not prepare statement
  

Я вижу, что создано два псевдонима для batch -> batch2 и batch6. Почему? Могу ли я как-то обойти это?

Комментарии:

1. «Могу ли я как-то обойти это?» — Я бы так не подумал, потому FETCH JOIN что s не может быть псевдоним, поэтому, когда вы scan.batch снова ссылаетесь на запрос, это обязательно будет отдельное соединение. Вместо этого вы можете попробовать использовать обычные соединения и предоставить график загрузки для запроса, хотя это, вероятно, просто приведет к разделению SELECT

2. Кроме того, зачем извлекать ScanMetaLetter.scan ? Разве он уже не загружен с нетерпением?