Spring Hibernate TransientPropertyValueException после удаления oneToOne - PullRequest
0 голосов
/ 25 мая 2018

Мне нужна помощь в разрешении спящего режима TransientPropertyValueException

У нас есть две сущности:

@Entity
@Table(name = "TABLE_A")
public class TableA {
    @Id
    @Column(name = "EXT_ID", nullable = false, unique = true, updatable = false)
    private String extId;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "EXT_ID", updatable = false, insertable = false)
    private TableB tableB;

   (...)
}

@Entity
@Table(name = "TABLE_B")
public class TableB  {
    @Id
    @Column(name = "EXT_ID", nullable = false)
    private String extId;

    @OneToOne
    @JoinColumn(name = "EXT_ID")
    private TableA tableA;
}

Теперь мы удаляем TableA, используя CrudRepository:

@Override
@Transactional
public boolean cancel(String extId) {
    Optional<TableA> maybeTableA = repository.findTableA(extId, DELETE_STATUS_SET);

    return maybeTableA.map(tableA -> {
        repository.delete(tableA);
        return true;
    }).orElse(false);
}

Пока все отлично работает.Но теперь, когда я хочу запросить TableB, который имел ссылку на TableA, я получаю TransientPropertyValueException Очевидно, что ссылка от TableB до TableA не была удалена до совершениятранзакция.

Есть хороший способ решить эту проблему?Я пытался sessionFactory.getCurrentSession().flush() непосредственно после удаления, но он также не работает

Единственная альтернатива, которая сработала, - это ручное удаление ссылки в транзакции:

tableB.setTableA(null);
tableBRepository.save(tableB);

Но это немногонемного хаки IMO

Ответы [ 3 ]

0 голосов
/ 25 мая 2018

Вы смотрели на каскад?Я сам выбрал бы ваш хакерский подход, так как мне легче читать и следовать в коде.

JPA @ManyToOne с CascadeType.ALL

0 голосов
/ 26 мая 2018

Когда речь идет об отношениях JPA, вы обязаны обновить обе стороны отношения.

Здесь метод cancel должен обновлять как tableA, так и tableB.В противном случае вы получите значение EXT_ ID в таблице B, которое не имеет соответствия в таблице A.Затем, после извлечения сущности tableB, Hibernate ожидает соответствующую сущность tableA, которая больше не существует и выдает ошибку.

TableB extId должен быть обнуляемым, если сущность tableB должна оставаться, когда ее соответствующаяtableA сущность удалена.

Еще одна вещь: как и в TableA, для TableB будет необходимо объявить либо extId, либо tableA как updatable = false, insertable = false.Hibernate не любит два доступных для записи свойства в одном поле базы данных.

@Override
@Transactional
public boolean cancel(String extId) {
    Optional<TableA> maybeTableA = repository.findTableA(extId, DELETE_STATUS_SET);

    return maybeTableA.map(tableA -> {

        // update tableB
        TableB tableB = tableA.getTableB();
        tableB.setExtId(null);
        tableB.setTableA(null);
        tableBRepository.save(tableB);

        // and update tableA
        repository.delete(tableA);
        return true;
    }).orElse(false);
}
0 голосов
/ 25 мая 2018
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...