Сбой при удалении внешнего ключа, потому что Hibernate не удаляет сначала связь - PullRequest
0 голосов
/ 16 апреля 2020

У меня проблема с ошибкой ограничения, когда я каскадно удаляю сущность, которая ссылается на другую сущность.

Я использую Hibernate в качестве провайдера JPA.

Домен модель:

ERD

  • Каждый Zone может иметь больше Actions, но Actions не распределяются между Zones ( OneToMany ).
  • TeleportAction (один из возможных видов Action) содержит набор Zones в качестве целей. Каждый TeleportAction может иметь больше Zones в качестве целей и Zones, и они могут использоваться несколькими TeleportActions ( ManyToMany ).

Как работает удаление

  1. Я звоню ZoneManager.deleteZone(zone)
    1. ZoneManager сначала проходит через все Zones и их TeleportActions и удаляет удаленные Zone из своих целей.
    2. После этого ZoneManager удаляет Zone из списка Zones
  2. Затем я удаляю Zone из БД с помощью Hibernate через session.delete(zone). Эта операция распространяется на Actions.
  3. Элемент списка

Сначала вызывается ZoneManager.deleteZone(zone), который работает так:

public void deleteZone(Zone removedZone) {

    // Remove this zone from all TeleportActions
    for (Zone zone : zones) {
        for (Action action : zone.getActions()) {
            if (action instanceof TeleportAction) {
                ((TeleportAction)action).removeTarget(removedZone);
            }
        }
    }

    // Finally remove zone
    zones.remove(removedZone);
}

, затем вызывающая сторона удаляет Zone из БД. Я хочу, чтобы Hibernate автоматически подтвердил, что я удалил эту Zone из Action целей.

session.delete(removedZone);

Ошибка, которую я получаю

Hibernate: /* delete cz.iwitrag.greencore.gameplay.zones.Zone */ delete from gcore_Zone where id=?
[org.hibernate.engine.jdbc.spi.SqlExceptionHelper] SQL Error: 1451, SQLState: 23000
[org.hibernate.engine.jdbc.spi.SqlExceptionHelper] Cannot delete or update a parent row: a foreign key constraint fails (`309145_mysql_db`.`gcore_tpaction_targetzones`, CONSTRAINT `FK4rvpdg8xjyt6lk5281jbi78c5` FOREIGN KEY (`targetZone_id`) REFERENCES `gcore_Zone` (`id`))
[org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] HHH000010: On release of batch it still contained JDBC statements
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
...

Эта ошибка вызвана тем, что когда я удалите Zone, это все еще цель некоторых TeleportActions.

Даже если я удалил это Zone из TeleportAction's целей в бизнес-коде до вызова session.delete(zone), Hibernate не подтверждает это и не удаляет Zone из ManyToMany ассоциации.

Entities

Zone, который имеет список Actions

@Entity
public class Zone {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true)
    @Cascade(CascadeType.ALL)
    @OrderColumn(name = "list_id")
    @JoinColumn(name = "zone_id")
    private List<Action> actions = new ArrayList<>();
...
}

Action, который является суперклассом TeleportAction

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "actionType")
public abstract class Action {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
...
}

TeleportAction, который содержит Набор Zones в качестве целей телепортации.
Обратите внимание, что это отношение отличается от Zone->Action отношения.

@Entity
@DiscriminatorValue("tp")
public class TeleportAction extends Action {

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "tpaction_targetzones", joinColumns = @JoinColumn(name="tpAction_id"), inverseJoinColumns = @JoinColumn(name="targetZone_id"))
    private Set<Zone> targets = new HashSet<>();
...
}

Вопрос

Как заставить Hibernate автоматически удалить удалено Zone из таблицы tpaction_targetzones перед тем, как он действительно удалит Zone из базы данных, чтобы избежать ошибки ограничения внешнего ключа?

...