简体   繁体   中英

JPQL Update Statement with Join

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM