如何使用 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;
}
需要知道如何使用带有 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;
}