JPQL Update Statement with Join

五迷三道 提交于 2019-12-10 12:14:12

问题


I've never used JPQL before, and I need to use it to batch update the values in a specific column. The column exists in the table, but the entity class was set up without a variable for it. I can't use the exact data, but the setup would be something like this to give you an idea:

Database Columns

Books:
book_id book_title author_id

Authors:
author_id first_name last_name

JPA Entity Classes

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

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

In the Books entity class, there's a getter & setter for the author_id, but it calls it from the author entity. My dilemma now is I need to batch update all book_titles with the same author_id and I'm unsure how to write the JPQL query statement to do this. I tried:

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

and

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

Both queries said both b.author.authorId and b.author were invalid identifiers. Would it make be possible to write 2 separate queries? 1 query as a select statement where I can use joins and then the 2nd to update the result set of the first query?


回答1:


JPQL is a poor choice for the job. b.author.authorId is not allowed, as it would translate to an SQL JOIN. Neither does JPQL support subqueries in UPDATE statements. You could map the author_id to a property in Books:

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

With the above in place, you could just do:

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

but you would have to live with altering your domain model just to acommodate a single case with an UPDATE query.

You should be able to split the task into two queries like so:

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();

Or, you could simply update the entities from code:

em.createQuery("SELECT b.id FROM Books b WHERE b.author.id = :authorId", Book.class)
    .setParameter("authorId", authorId)
    .getResultList()
    .forEach(book -> book.setBookTitle(bookTitle));


来源:https://stackoverflow.com/questions/50107418/jpql-update-statement-with-join

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!