Оптопланнер и база данных

#java #sql-server #hibernate #jpa #optaplanner

Вопрос:

В настоящее время я кодирую с помощью optaplanner и использую SQL Server для базы данных.

моя система продолжает выдавать эту ошибку:

com.microsoft.sqlserver.jdbc.SQLServerException: Недопустимое имя столбца «stockLocations_StockLocationID»

Я проверил и все мои имена переменных в своей базе данных, и все они верны.

Вот мои текущие занятия:

классы shopify:

 @PlanningEntity
@Entity
@DataSource("Shopify")
public class Shopify extends PanacheEntityBase{

@PlanningId
@Id
private Long ShopifyID;
private String CustomerName;
private String ProductSKU;

@PlanningVariable(valueRangeProviderRefs = "stocklocationRange")
@ManyToOne
private StockLocations stockLocations;

public Shopify(Long ShopifyID, String customerName, String productSKU) {
    this.ShopifyID = ShopifyID;
    this.CustomerName = customerName;
    this.ProductSKU = productSKU;
}

public Shopify(Long shopifyID, String customerName, String productSKU, StockLocations 
stockLocations) {
    ShopifyID = shopifyID;
    CustomerName = customerName;
    ProductSKU = productSKU;
    this.stockLocations = stockLocations;
}
 

Класс размещения запасов:

 @Entity
@DataSource("StockLocations")
public class StockLocations extends PanacheEntityBase {

@PlanningId
@Id
@GeneratedValue
public Long StockLocationID;
public String ProductSKU;
public String StockLocation;

public StockLocations(Long stockLocationID, String productSKU, String stock_Location) {
    this.StockLocationID = stockLocationID;
    ProductSKU = productSKU;
    StockLocation = stock_Location;
}

public StockLocations() {

}
 

Класс allDetails

 @PlanningSolution
public class AllDetails {

@PlanningEntityCollectionProperty
private List<Shopify> shopifyList;

@ProblemFactCollectionProperty
@ValueRangeProvider(id = "stocklocationRange")
private List<StockLocations> stockLocationsList;

@PlanningScore
private HardSoftScore score ;

private SolverStatus solverStatus;


public AllDetails(){

}

public AllDetails( List<StockLocations> stockLocationsList, List<Shopify> shopifyList) {
    this.stockLocationsList = stockLocationsList;
    this.shopifyList = shopifyList;
   // this.shopifyStockLocationsList = shopifyStockLocationsList;
}
 

а вот основной функциональный файл javascript, используемый для отображения данных в пользовательском интерфейсе

 function refreshAllDetails() {
    $.getJSON("allDetails", function (allDetails) {
        refreshSolvingButtons(allDetails.solverStatus != null amp;amp; allDetails.solverStatus !== 
"NOT_SOLVING");
        $("#score").text("Score: "   (allDetails.score == null ? "?" : allDetails.score));

         const timeTableByRoom = $("#timeTableByRoom");
         timeTableByRoom.children().remove();
         const timeTableByTeacher = $("#timeTableByTeacher");
         timeTableByTeacher.children().remove();
         const timeTableByStudentGroup = $("#timeTableByStudentGroup");
         timeTableByStudentGroup.children().remove();
         const unassignedSKUs = $("#unassignedSKUs");
         unassignedSKUs.children().remove();

        //Picking Station Function
        const theadByRoom = $("<thead>").appendTo(timeTableByRoom);
        const headerRowByRoom = $("<tr>").appendTo(theadByRoom);
        headerRowByRoom.append($("<th>Picking Stations</th>"));
        $.each(allDetails.stockLocationsList, (index, stockLocations) => {
            headerRowByRoom
                .append($("<th/>")
                    .append($("<span/>").text(stockLocations.stockLocation))
                    .append($(`<button type="button" class="ml-2 mb-1 btn btn-light btn-sm p- 
1"/>`)
                    .append($(`<small class="fas fa-trash"/>`)
                    ).click(() => deleteRoom(stockLocations))));
    });

//IT WORKS!!! UNASSIGNED SKUS
    $.each(allDetails.shopifyList, (index, shopify) => {
        const color = pickColor(shopify.product_SKU)
        const lessonElementWithoutDelete = $(`<div class="card lesson" style="background- 
color: ${color}"/>`)
        .append($(`<div class="card-body p-2"/>`)
            .append($(`<h5 class="card-title mb-1"/>`).text(shopify.customerName))
            .append($(`<p class="card-text ml-2 mb-1"/>`)
                .append($(`<em/>`).text(`Product SKU: ${shopify.product_SKU}`)))
            .append($(`<small class="ml-2 mt-1 card-text text-muted align-bottom float
            right"/>`).text(shopify.id)))
            //append($(`<p class="card-text ml-2"/>`).text(shopify.billing_Name_Added)));
    const lessonElement = lessonElementWithoutDelete.clone();
    lessonElement.find(".card-body").prepend(
        $(`<button type="button" class="ml-2 btn btn-light btn-sm p-1 float-right"/>`)
            .append($(`<small class="fas fa-trash"/>`)
            ).click(() => deleteLesson(shopify))
    )
    if (Shopify.stockLocations == null) {
        unassignedSKUs.append(lessonElement);
    }
    
 });

 });
 }
 

Ответ №1:

Это проблема с гибернацией JPA и JDBC, которая не связана с OptaPlanner.

«com.microsoft.sqlserver.jdbc.SQLServerException: Недопустимое имя столбца «stockLocations_StockLocationID»»

Это означает, что эта конфигурация Hibernate-JPA:

 @Entity ...
public class StockLocations extends PanacheEntityBase {

...
@Id
@GeneratedValue
public Long StockLocationID;
 

не соответствует схеме таблицы базы данных. В таблице SQL для этой сущности нет столбца SQL с именем SotckLocationID. Вероятно, это только верхушка айсберга.

В программе быстрого запуска optaplanner quarkus-школьное расписание, мы используем

 quarkus.hibernate-orm.database.generation=drop-and-create
 

уничтожить всю базу данных и моделировать ее на 100%, как модель, каждый раз, когда она запускается. Это отлично подходит для разработки по мере изменения модели (очевидно, очень плохо для производства).

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

1. Моя база данных содержит поле, и имя в коде также правильное, я, кажется, не могу понять, почему оно продолжает выдавать эту ошибку, но я попробую ваш код кваркуса, спасибо!

2. существуют ли какие-либо примеры optaplanner, в которых используются реальные базы данных?

3. быстрый запуск quarkus-school-расписания использует базу данных H2 в памяти. Его можно легко переключить на postgresql, mysql, mariadb и т.д. Для получения информации о том, как это сделать, перейдите в quarkus-quickstarts и найдите примеры hibernate-jpa или panache, в которых используется postgresql.