JPA Criteria API使用子类型类生成额外的内部联接

问题描述

我们有Case,Meeting和SpecialMeeting 3类(下面的zie对象)。当我们通过以下方式使用JPA Criteria Api时:

    static Specification<Case> betweenEnddateSpecialMeeting(LocalDate start,LocalDate end) {
        return (root,query,cb) -> {
            if (start != null || end != null) {
                Join<Case,SpecialMeeting> join = cb.treat(root.join(Case_.meetings),SpecialMeeting.class);
                Path<LocalDate> pathEnddate = join.get(SpecialMeeting_.actuelEnddate);

                return findByStartAndEndDate(start,end,cb,pathEnddate);
            } else {
                return null;
            }
        };
    }
    private static Predicate findByStartAndEndDate(LocalDate start,LocalDate end,CriteriaBuilder cb,Path<LocalDate> pathEnddate) {
        if (start != null && end != null) {
            return cb.and(cb.greaterThanorEqualTo(pathEnddate,start),cb.lessthanorEqualTo(pathEnddate,end));
        } else if (start != null) {
            return cb.greaterThanorEqualTo(pathEnddate,start);
        } else {
            return cb.lessthanorEqualTo(pathEnddate,end);
        }
    }

Hibernate生成以下查询

    select
        case0_.id as id1_73_,case0_.identificationcode as identifi8_73_,case0_.version as version15_73_
    from
        l_cases case0_ 
    inner join
        l_meetings meeting1_ 
            on case0_.id=meeting1_.case_id 
    inner join
        l_meetings meeting2_ 
            on case0_.id=meeting2_.case_id 
    inner join
        l_special_meetings meeting2_1_ 
            on meeting2_.id=meeting2_1_.id 
    where
        meeting2_1_.actuel_enddate<=?

我们用于SpecialMeeting子类型的cb.treat(root.join(Case_.meetings),SpecialMeeting.class), 为l_meetings生成一个额外的内部联接。这将导致重复的记录。 有人可以帮助我们为l_meetings上的1个内部联接获取正确的查询吗?

我们正在使用以下版本:

休眠5.4.20-Final
spring-boot:2.3.3。发布

此致,
安德烈·托伦斯玛(Andre Torensma)

上面示例中使用的实体。

@Slf4j
@Audited
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "L_CASES")
@SequenceGenerator(name = "LCN",sequenceName = "L_CASE_SEQ",allocationSize = 1)
public class Case implements IdentifiableEntity {

    @Id
    @Column(nullable = false,precision = 10)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "LCN")
    private Long id;
    @Version
    private Long version;
    @Column(precision = 50)
    private String identificationcode;
    @Valid
    @OnetoMany(mappedBy = "case",cascade = { CascadeType.ALL })
    private List<Meeting> meetings = new ArrayList<>();

    @Override
    public String getidentificationCode() {
        return identificationcode;
    }
}


@Slf4j
@Audited
@Getter
@Setter
@Entity
@NoArgsConstructor
@Inheritance(strategy = InheritanceType.JOINED)
@discriminatorColumn(name = "TYPE",length = 2,discriminatorType = discriminatorType.STRING)
@Table(name = "L_MEETINGS")
@SequenceGenerator(name = "LMS",sequenceName = "L_MEETINGS_SEQ",allocationSize = 1)
public class Meeting {
    @Id
    @Column(nullable = false,generator = "LMS")
    private Long id;
    @Version
    private Long version;
    @Column(length = 36)
    private String identificationcode;
    @Column(nullable = false)
    private LocalDate ldate;
    @Column(name = "DATETIME_REGISTRATION",nullable = false)
    private LocalDateTime datetimeRegistration;
    @OnetoOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "MEETING_ID")
    private Meeting relatedMeeting;
    @ManyToOne
    @JoinColumn(name = "CASE_ID",nullable = false)
    private Case case;

    public Optional<SpecialMeeting> getSpecialMeeting() {
        if (this instanceof SpecialMeeting) {
            return Optional.of((SpecialMeeting) this);
        }
        return Optional.empty();
    }
}


@Audited
@Getter
@Setter
@Entity
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(name = "L_SPECIAL_MEETINGS")
@discriminatorValue("BB")
public class SpecialMeeting extends Meeting {
    @Column
    private LocalDate startdate;
    @Column
    private LocalDate enddate;
    @Column(name = "ACTUEL_ENDDATE")
    private LocalDate actuelEnddate;
    @Column
    private String description;

}```

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)