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

У меня есть объект 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 для удаления записей из таблицы соединений? Если нет, я могу просто загрузить все объекты Role и удалить записи из коллекции privs каждого из них, а затем сохранить каждую роль. Но это кажется глупым, если простой JPQL-запрос сделает все сразу.


person HappyEngineer    schedule 02.07.2009    source источник


Ответы (3)


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

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

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

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

person cliff.meyers    schedule 02.07.2009

Я также искал подход JPQL для удаления отношения «многие ко многим» (содержащегося в таблице соединений). Очевидно, что в ORM нет понятия таблиц, поэтому мы не можем использовать операции DELETE... Но я бы хотел, чтобы для этих случаев был специальный оператор. Что-то вроде LINK и UNLINK. Может будущая функция?

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

Например, если у меня есть класс Student, который имеет отношение «многие ко многим» с курсами:

@ManyToMany
private Collection <Courses> collCourses;

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

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

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

person negora    schedule 19.07.2009

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

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

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

person DataNucleus    schedule 03.07.2009