如何使用 select 语句执行插入以使用 HQL 放入多行

How to perform an insert with a select statement to put in multiple rows with HQL

需要知道如何使用带有 select 且 select 包含联合的 HQL 进行插入。这是我的测试用例

create table simple_author (
id bigint generated by default as identity,
first_name varchar(255),
last_name varchar(255),
primary key (id))

@Entity
public class SimpleAuthor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
private String firstName;
private String lastName;}

假设要求是插入 2 位作者,如果其中一位作者因任何原因失败,则另一位作者不会保存在数据库中。

仅使用 SQL 如果 Oracle 或 H2 我可以做到 插入 simple_author(first_name, last_name) select 'bob', 'smith' 来自 dual union select 'frank', 'brown' 来自 dual

或者如果使用 SQL 服务器: 插入 simple_author(first_name, last_name) select ‘bob’, ‘smith’ union select ‘frank’, ‘brown’

假设 Bob Smith 和 Frank Brown 由在 UI.

中输入数据的用户提供

正在查看https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#hql-insert 似乎支持一个简单的案例。 似乎有几个问题: 在这种情况下做联合和要添加的值列表 bob smith 和 frank brown 对于工会,已经尝试了几个解决方案,如线程

中所示

Hibernate Union alternatives

How to execute query with union in hibernate?

充其量他们似乎只是接近要求。 所以问题是如何写: 插入 simple_author(first_name, last_name) select ‘bob’, ‘smith’ from dual union select ‘frank’, ‘brown’ from dual 在 hsql

很遗憾HQL/JPQL不支持这个。这些事情可以通过本机查询或像 FluentJPA 这样的技术来完成,它在幕后进行本机查询。

至少对我来说,我使用的是 Spring,并且在撰写本文时并不知道在 DAO 中 Spring 使用 @Transactional 注释将管理提交。发现实体管理器将根据是否发生异常来提交或回滚所有行,因此我可以达到提交 "all or nothing" 的目标。所以在我的例子中,代码是:

  // if an exception occurs then the transaction is rolled back there is not any
  // special code required.
  public List<SimpleAuthor> insertSimpleAuthors(List<SimpleAuthor> simpleAuthors) {   
   // try {
      //em.getTransaction().begin();
      for (SimpleAuthor entity : simpleAuthors) {
        em.persist(entity);     
      }
      //em.flush();
//    } catch (Exception ex) {
//      em.getTransaction().rollback();
//      throw ex;
//    }
    for (int i = 0; i < simpleAuthors.size(); i++) {
      //SimpleAuthor entity : simpleAuthors) {
      simpleAuthors.set(i, 
      em.createQuery("from SimpleAuthor where firstName = :firstName and lastName = :lastName",SimpleAuthor.class)
       .setParameter("firstName", simpleAuthors.get(i).getFirstName())
       .setParameter("lastName", simpleAuthors.get(i).getLastName())
       .getSingleResult()
       );
    }
    return simpleAuthors;
  }