Удаление JPA с двумя взаимосвязанными классами сущностей

StackOverflow https://stackoverflow.com/questions/807547

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть 2 EJB 3 Entity Beans:

@Entity
public class Organisation
{
    @Id
    @Column(length = 64)
    private String guid;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    @JoinColumn(name = "home_unit_fk", nullable = true)
    private Unit homeUnit;          
}

@Entity
public class Unit
{
    @Id
    @Column(length = 64)
    private String guid;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "organisation_fk", nullable = false)
    private Organisation organisation;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_unit_fk", nullable = true)
    private Unit parentUnit;

    @OneToMany(mappedBy = "parentUnit", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    @OrderBy("shortName")
    @OptimisticLock(excluded = true)
    private Set<Unit> childUnits;   
}

Если я удалю организацию, используя стандартный Dao:

public int deleteByGuid(final String guid) 
{
    final Query query = entityManager.createQuery("delete from " + getPersistentClass().getName() + " where guid = :guid");
    query.setParameter("guid", guid);
    return query.executeUpdate();
}

Но я получаю следующее исключение:

com.mysql.jdbc.Exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Невозможно удалить или обновить родительскую строку:ограничение внешнего ключа не выполнено (config.unit, ОГРАНИЧЕНИЕ FK27D184F5D4393D ВНЕШНИЙ КЛЮЧ (organisation_fk) ИСПОЛЬЗОВАННАЯ ЛИТЕРАТУРА organisation (guid))

Я этого не понимаю.Что я делаю не так?Разве JPA/Hibernate не должен выполнять удаление как для подразделения, так и для организации в рамках одной транзакции?

Это было полезно?

Решение

Запрос на массовое удаление не загружает объекты в память и обходит любой каскад, указанный в ассоциациях.

Я бы закодировал ваш метод удаления как:

public int deleteByGuid(final String guid){
    Organization org = entityManager.find(Organization.class, guid);
    entityManager.remove(org);
}

Если вы используете запрос для выполнения массовых обновлений, операция делегируется непосредственно базе данных.Если вы хотите удалить дочерние объекты, вам необходимо установить триггер DELETE CASCADE на уровне «базы данных».

Загрузив объект и удалив его, Hibernate запустит каскад на уровне «объекта».

Дополнительная информация доступна по адресу: http://twasink.net/blog/2005/04/differences-in-behaviour-between-hibernate-delete-queries-and-the-old-way/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top