NullPointerException в CompareTo при сохранении модифицированной сущности с отношением ManyToOne - PullRequest
0 голосов
/ 23 сентября 2019

Сводка (код ниже)

У меня есть объект ProcessInstance с отношением ManyToOne с объектом ExpectedBusinessTimestamp.В контроллере я загружаю ProcessInstance (в том числе ExpectedBusinessTimestamp), изменяю поле и затем сохраняю ProcessInstance.

Операция сохранения завершается неудачно с NullPointerException в методе сравнения ToTexpectedBusinessTimestamp, потому что левый объект ( этот объект в CompareTo) не был загружен должным образом.Объект this не равен NULL, но заполнен только его идентификатор, все остальные поля имеют значение NULL.

Я думаю, что по какой-то причине во время сохранения ProcessInstanceперезагружается из базы данных, но по какой-то причине не загружает с ним ExpectedBusinessTimestamp, даже если для FetchType явно задано значение EAGER.Когда операция сохранения затем сравнивает сохраненный ProcessInstance с тем, который находится в памяти, в какой-то момент сравниваются ExpectedBusinessTimestamps, но тот из базы данных не загружается, что приводит к исключению NullPointerException.

Код: ProcessInstance

@Entity
public class ProcessInstance{

    @ManyToOne
    private ExpectedBusinessTimestamp expectedBusinessTimestamp;
    public ExpectedBusinessTimestamp getExpectedBusinessTimestamp() {
        return expectedBusinessTimestamp;
    }
    public void setExpectedBusinessTimestamp(ExpectedBusinessTimestamp expectedBusinessTimestamp){
        this.expectedBusinessTimestamp = expectedBusinessTimestamp;
    }
}

Код: ExpectedBusinessTimestamp

@Entity
public class ExpectedBusinessTimestamp {
    @OneToMany(mappedBy = "expectedBusinessTimestamp")
    List<ProcessInstance> processInstances;
    public List<ProcessInstance> getProcessInstances(){ return processInstances; }
}

Код: контроллер

ProcessInstance previousInstance = processInstanceRepository.findPrevious(
                processDefinition, expectedBusinessTimestamp);
previousInstance.setLatestVersion(false);
processInstanceRepository.save(previousInstance);

Подробнее

Классы кода, конечно, немного сложнее, чем показано, но я не хотел вставлять здесь весь код.Если что-то релевантное отсутствует, пожалуйста, дайте мне знать.

Отладка позволила мне подтвердить:

  • В хранилище есть AutoWired in.
  • Загружен предыдущий экземпляр (включая ExpectedBusinessTimestamp)
  • При сохранении сущность загружается из базы данных (это глубоко в стеке вызовов, спящий режим jpa и т. д., а не в моем коде).
  • При сохранении сравниватьExpectBusinessTimestamp неоднократно вызывается.В одном из этих случаев, ExpectedBusinessTimestamp имеет только заполненный Id, все остальные поля являются пустыми.При сравнении этих полей выдается исключение NullPointerException.

1 Ответ

0 голосов
/ 26 сентября 2019

Причиной проблемы была еще одна сущность, которая имеет отношение OneToMany с ExpectedBusinessTimestamp как SortedSet и снабжена аннотацией @SortNatural.SortedSet обеспечивает использование Comparable-интерфейса, поэтому во-первых, в классе ExpectedBusinessTimestamp был метод CompareTo.

Изменение SortedSet на List и использование аннотации @OrderBy вместо @SortNatural имеетрешены все проблемы.

@OneToMany(mappedBy = "expectedBusinessTimestampTemplate", orphanRemoval = true, cascade = CascadeType.ALL)
@OrderBy("date asc, time asc")
private List<ExpectedBusinessTimestamp> expectedBusinessTimestamps;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...