【问题标题】:JPQL Update Statement with Join带有 Join 的 JPQL 更新语句
【发布时间】:2018-10-10 22:57:20
【问题描述】:

我以前从未使用过 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;

在 Books 实体类中,author_id 有一个 getter 和 setter,但它从 author 实体调用它。我现在的困境是我需要使用相同的 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个查询作为选择语句,我可以使用连接然后第二个来更新第一个查询的结果集?

【问题讨论】:

    标签: java hibernate jpa jpql


    【解决方案1】:

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

    【讨论】:

    • 拆分查询就可以了。应用程序很大,所涉及的实体是应用程序的核心,所以我不想尽可能更改实体类,可能一次需要更新 1000 多条记录,所以我也没有不想单独迭代它们中的每一个。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    • 2012-03-28
    • 2014-08-17
    • 1970-01-01
    • 2015-09-28
    相关资源
    最近更新 更多