Как мне использовать JPQL для удаления записей из таблицы объединения?

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

  •  21-08-2019
  •  | 
  •  

Вопрос

У меня есть объект JPA, который имеет отношение "многие ко многим", подобное этому:

@Entity
public class Role {
    //...

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
    name="RolePrivilege",
    joinColumns=
        @JoinColumn(name="role", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="privilege", referencedColumnName="ID")
    )
    private Set<Privilege> privs;
}

Для RolePrivilege нет объекта JPA, поэтому я не уверен, как написать запрос JPQL для удаления записей из поля privs объекта роли.Например, я пробовал это, но это не сработало.Он жалуется, что Role.privs не сопоставлен.

DELETE FROM Role.privs p WHERE p.id=:privId

Я не уверен, что еще можно попробовать.Конечно, я мог бы просто написать собственный запрос, который удаляет из таблицы объединения RolePrivilege.Но я обеспокоен тем, что это будет плохо взаимодействовать с локально кэшированными объектами, которые не будут обновляться собственным запросом.

Возможно ли вообще написать JPQL для удаления записей из таблицы соединений, подобной этой?Если нет, я могу просто загрузить все объекты роли и удалить записи из коллекции privs каждого из них, а затем сохранить каждую роль.Но кажется глупым делать это, если простой JPQL-запрос сделает все это сразу.

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

Решение

Инструкции JPQL update и delete должны ссылаться на имя объекта, а не на имя таблицы, поэтому я думаю, вам не повезло с предложенным вами подходом.

В зависимости от вашего поставщика JPA, вы можете удалить записи из объединяемой таблицы, используя простой необработанный оператор SQL (должен быть переносимым на 100%), а затем программно взаимодействовать с вашим API поставщика кэша, чтобы удалить данные.Например, в режиме гибернации вы можете вызвать функцию evict(), чтобы истечь срок действия всех коллекций "Role.privs" из кэша 2-го уровня:

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs
sessionFactory.evictCollection("Role.privs"); //evict all privs collections

К сожалению, я недостаточно работаю с API JPA, чтобы точно знать, что именно поддерживается.

Другие советы

Я также искал подход JPQL для удаления отношения "многие ко многим" (содержащегося в таблице объединения).Очевидно, что в ORM нет понятия таблиц, поэтому мы не можем использовать операции УДАЛЕНИЯ...Но я хотел бы, чтобы для таких случаев был специальный оператор.Что-то вроде СВЯЗЫВАНИЯ и РАЗЪЕДИНЕНИЯ.Может быть, это будущая функция?

В любом случае, то, что я делал для достижения этой цели, заключалось в работе с коллекциями, реализованными в компонентах entity, которые отображают отношения "многие ко многим".

Например, если у меня есть Ученик класса, который имеет отношение "многие ко многим" к Курсам:

@ManyToMany
private Collection <Courses> collCourses;

Я создаю в сущности средство получения и установки для этой коллекции.Затем, например, из EJB, я извлекаю коллекцию с помощью getter, добавляю или удаляю нужный курс и, наконец, использую setter для назначения новой коллекции.И это сделано.Это работает безукоризненно.

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

Потому что для меня это так же неэффективно, как извлекать реестры из таблицы и послефильтровывать их, используя чистую Java вместо языка запросов, который работает прямо или непрямо с внутренним движком БД (SQL, JPQL ...).

Java - это объектно-ориентированный язык, и весь смысл ORM заключается в том, чтобы скрыть от вас детали таблиц объединения и тому подобного.Следовательно, было бы странно даже рассматривать возможность удаления из таблицы объединения без учета последствий.

Нет, вы не можете сделать это с помощью JPQL, то есть для сущностей.

Извлеките объекты с обоих концов и очистите их коллекции.Это приведет к удалению записей в таблицах объединения.Объектно-ориентированный.

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