带有 Join 的 JPQL 更新语句
JPQL Update Statement with Join
我以前从未使用过JPQL,我需要使用它来批量更新特定列中的值。该列存在于 table 中,但实体 class 是在没有为其设置变量的情况下设置的。我不能使用确切的数据,但设置会像这样给你一个想法:
数据库列
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;
在图书实体 class 中,author_id 有一个 getter 和 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 语句,我可以在其中使用连接,然后第二个查询更新第一个查询的结果集?
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));
我以前从未使用过JPQL,我需要使用它来批量更新特定列中的值。该列存在于 table 中,但实体 class 是在没有为其设置变量的情况下设置的。我不能使用确切的数据,但设置会像这样给你一个想法:
数据库列
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;
在图书实体 class 中,author_id 有一个 getter 和 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 语句,我可以在其中使用连接,然后第二个查询更新第一个查询的结果集?
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));