Статьи

Интеграция JPA Hibernate с OptaPlanner

Мы улучшаем интеграцию OptaPlanner с остальной частью JEE, поэтому проще создавать приложения для конечных пользователей, которые просто работают. Давайте посмотрим на улучшенную интеграцию JPA Hibernate.

Основы

Как JPA Hibernate, так и OptaPlanner работают с POJO (Plain Old Java Objects), поэтому просто добавьте несколько аннотаций JPA к объектам вашего домена, чтобы сохранить их в JPA Hibernate, и добавьте некоторые аннотации OptaPlanner, чтобы решить вашу проблему оптимизации с OptaPlanner.

Для каждого класса фактов проблемы обычно есть только аннотации JPA:

01
02
03
04
05
06
07
08
09
10
@Entity // JPA annotation
public class Computer {
 
    private int cpuPower;
    private int memory;
    private int networkBandwidth;
    private int cost;
 
    ...
}

Для каждого класса объекта планирования имеются аннотации JPA и OptaPlanner:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
@PlanningEntity // OptaPlanner annotation
@Entity // JPA annotation
public class Process {
 
    private int requiredCpuPower;
    private int requiredMemory;
    private int requiredNetworkBandwidth;
 
    @PlanningVariable(...) // OptaPlanner annotation
    @ManyToOne() // JPA annotation
    private Computer computer;
 
    ...
}

Не путайте объект JPA (любой объект, который сохраняется в базе данных) с объектом планирования OptaPlanner (объект, который изменяется в ходе решения OptaPlanner).

Сохраняя счет

По умолчанию JPA Hibernate помещает Score в столбец BLOB посредством сериализации Java. Это нежелательно, поскольку мешает использовать оценку в запросе JPA-QL. Кроме того, он вызывает проблемы с базой данных при обновлении версии OptaPlanner.

Поэтому в OptaPlanner 6.4.0.Beta1 есть новый jar optaplanner-persistence-jpa который содержит тип Hibernate для каждого типа оценки. Используйте это так:

01
02
03
04
05
06
07
08
09
10
@PlanningSolution // OptaPlanner annotation
@Entity // JPA annotation
@TypeDef(defaultForType = HardSoftScore.class, typeClass = HardSoftScoreHibernateType.class) // Hibernate annotation
public class CloudBalance implements Solution<HardSoftScore> {
 
    @Columns(columns = {@Column(name = "hardScore"), @Column(name = "softScore")}) // JPA annotation
    private HardSoftScore score;
 
    ...
}

Это помещает HardSoftScore в 2 столбца INTEGER вместо столбца BLOB . Справочное руководство OptaPlanner содержит больше информации о том, как правильно обращаться с BigDecimal и / или сгибаемыми партитурами.

Ловушка клонирования

В модели JPA распространено, что факты проблемы ссылаются на решение планирования, которое может повредить клонирование планирования (если используется клонер планирования по умолчанию).

Чтобы преодолеть это, просто аннотируйте классы фактов проблемы, которые ссылаются на решение планирования или объект планирования, с помощью аннотации @DeepPlanningClone :

1
2
3
4
5
6
7
8
9
@DeepPlanningClone // OptaPlanner annotation: Force the default planning cloner to planning clone this class too
@Entity // JPA annotation
public class Computer {
 
    @ManyToOne
    private CloudBalance cloudBalance;
 
    ...
}

Таким образом, класс Computer планирует клонирование, и поле клона cloudBalance будет указывать на клон CloudBalance .

Вывод

Вы можете использовать те же классы домена для JPA Hibernate и OptaPlanner, нет необходимости дублировать ваш домен!

Ссылка: Интеграция JPA Hibernate с OptaPlanner от нашего партнера JCG Джеффри Де Смета в блоге OptaPlanner .