Заявление об обновлении JPQL с помощью Join - PullRequest
0 голосов
/ 30 апреля 2018

Я никогда раньше не использовал JPQL, и мне нужно использовать его для пакетного обновления значений в определенном столбце. Столбец существует в таблице, но класс сущности был установлен без переменной для него. Я не могу использовать точные данные, но установка будет выглядеть примерно так:

Столбцы базы данных

Books:
book_id book_title author_id

Authors:
author_id first_name last_name

Классы сущностей JPA

Books:
private Integer bookId;
private String bookTitle;
private EAuthor author;

Authors:
private Integer authorId;
private String firstName;
private String lastName;

В классе сущности Книги есть метод получения и установки для author_id, но он вызывает его от сущности автора. Моя дилемма теперь заключается в том, что мне нужно обновить все book_titles с помощью одного и того же author_id, и я не уверен, как написать оператор запроса JPQL для этого. Я попробовал:

String queryUpdate = "UPDATE books b SET b.book_title = :bookTitle"
                            + " WHERE b.author = :authorId";

и

String queryUpdate = "UPDATE books b SET b.book_title = :bookTitle"
                            + " WHERE b.author.authorId = :authorId";

В обоих запросах говорилось, что b.author.authorId и b.author были недействительными идентификаторами. Можно ли было написать 2 отдельных запроса? 1 запрос как оператор выбора, где я могу использовать соединения, а затем 2-й, чтобы обновить результирующий набор первого запроса?

1 Ответ

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

JPQL - плохой выбор для работы. b.author.authorId не допускается, так как он переводится в SQL JOIN. JPQL также не поддерживает подзапросы в операторах UPDATE. Вы могли бы сопоставить author_id с недвижимостью в Books:

@Column(name = "author_id", insertable=false, updatable=false)
private Long authorId;

С учетом вышесказанного, вы можете просто сделать:

UPDATE Books b SET b.book_title = :bookTitle WHERE b.authorId = :authorId

но вам придется смириться с изменением модели вашего домена, чтобы объединить один случай с запросом UPDATE.

Вы должны иметь возможность разбить задачу на два запроса следующим образом:

List<Long> ids = em.createQuery("SELECT b.id FROM Books b WHERE b.author.id = :authorId", Long.class)
    .setParameter("authorId", authorId)
    .getResultList();
em.createQuery("UPDATE Books b SET b.bookTitle = :bookTitle WHERE b.id IN :ids")
    .setParameter("ids", ids)
    .setParameter("bookTitle", bookTitle)
    .executeUpdate();

Или вы можете просто обновить сущности из кода:

em.createQuery("SELECT b.id FROM Books b WHERE b.author.id = :authorId", Book.class)
    .setParameter("authorId", authorId)
    .getResultList()
    .forEach(book -> book.setBookTitle(bookTitle));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...