带有Join的JPQL更新语句

时间:2018-04-30 20:01:18

标签: java hibernate jpa jpql

我之前从未使用过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的setter,但它从作者实体调用它。我现在面临的困境是我需要使用相同的author_id批量更新所有book_titles,并且我不确定如何编写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个查询作为select语句,我可以使用连接,然后第2个更新第一个查询的结果集?

1 个答案:

答案 0 :(得分:3)

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