Optaplanner ConstraintFactory - 从似乎 return 个未初始化的实体

Optaplanner ConstraintFactory - from seems to return uninitialized entities

我正在尝试使用 Optaplanner 解决一个简单的概念验证问题,但我 运行 陷入了矛盾。文档(和其他 SO 问题)似乎表明 ConstraintFactory.from() 应该只 return 初始化规划实体。 (like here)

我有以下规划实体(仅相关代码):

@PlanningEntity
public class Enrollment {

    @PlanningId
    private UUID id;

    private Student student;
    @PlanningVariable(valueRangeProviderRefs = "possibleLessons", nullable = true)
    private Lesson lesson;

    // No-arg constructor required for OptaPlanner
    public Enrollment() {
    }

    public Enrollment(UUID id, Student student) {
        this.id = id;
        this.student = student;
    }

    public Student getStudent() {
        return student;
    }

    public Lesson getLesson() {
        return lesson;
    }
}

并尝试引入以下约束:

    private Constraint studentsLikePreferredSubjects(ConstraintFactory constraintFactory) {
        return constraintFactory
                .from(Enrollment.class)
                .filter(enrollment -> enrollment.getStudent().getPreferredSubjects().contains(enrollment.getLesson().getSubject()))
                .reward("Student likes subject bonus", HardSoftScore.ONE_SOFT);
    }

这段代码不起作用,因为我在 getLesson 上得到了空指针异常:Cannot invoke "Lesson.getSubject()" because the return value of "Enrollment.getLesson()" is null

但是,添加过滤器以过滤掉无效课程确实有效:

    private Constraint studentsLikePreferredSubjects(ConstraintFactory constraintFactory) {
        return constraintFactory
                .from(Enrollment.class)
                .filter(enrollment -> enrollment.getLesson() != null)
                .filter(enrollment -> enrollment.getStudent().getPreferredSubjects().contains(enrollment.getLesson().getSubject()))
                .reward("Student likes subject bonus", HardSoftScore.ONE_SOFT);
    }

当然我可以只使用这段代码,但我不明白为什么它是必要的:我希望不包含 Enrollments 和 null Lessons在流中,因为我使用的是 from(而不是 fromUnfiltered)。谁能解释这种行为?

ConstraintFactory.from() 仅 returns 初始化规划实体,除非 nullable = true(默认情况下,nullable 为 false,因此 from() 过滤器)。

在您的代码中,nullable = true(您正在执行过度约束规划),因此 from() returns 所有实体。