从JPA 2.0版开始, EntityManager提供了方法getCriteriaBuilder()来动态构建选择查询,而无需使用Java持久性查询语言(JPQL)进行字符串连接。 在2.1版中,此CriteriaBuilder提供了两个新方法createCriteriaDelete()createCriteriaUpdate() ,使我们可以使用条件API制定删除和更新查询的方法。

出于说明目的,让我们对两个实体PersonGeek使用简单的继承用例:

@Entity
@Table(name = "T_PERSON")
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {@Id@GeneratedValueprivate Long id;@Column(name = "FIRST_NAME")private String firstName;@Column(name = "LAST_NAME")private String lastName;...
}@Entity
@Table(name = "T_GEEK")
@Access(AccessType.PROPERTY)
public class Geek extends Person {private String favouriteProgrammingLanguage;...
}

要从我们的数据库中删除所有喜欢Java作为其编程语言的怪胎,我们可以使用EntityManager的新createCriteriaDelete()方法利用以下代码:

EntityTransaction transaction = null;
try {transaction = entityManager.getTransaction();transaction.begin();CriteriaBuilder builder = entityManager.getCriteriaBuilder();CriteriaDelete<Geek> delete = builder.createCriteriaDelete(Geek.class);Root<Geek> geekRoot = delete.from(Geek.class);delete.where(builder.equal(geekRoot.get("favouriteProgrammingLanguage"), "Java"));int numberOfRowsUpdated = entityManager.createQuery(delete).executeUpdate();LOGGER.info("Deleted " + numberOfRowsUpdated + " rows.");transaction.commit();
} catch (Exception e) {if (transaction != null && transaction.isActive()) {transaction.rollback();}
}

与纯SQL一样,我们可以使用from()方法指定要针对其发出删除查询的表,并使用where()声明谓词。 通过这种方式,标准API允许以动态方式定义批量删除操作,而无需使用过多的字符串连接。

但是,SQL是如何创建的呢? 首先,ORM提供程序必须注意,我们正在使用策略JOINED从继承层次结构中删除,这意味着我们有两个表T_PERSONT_GEEK ,其中第二个表存储对父表的引用。 Hibernate版本4.3.8.Final创建以下SQL语句:

insert
intoHT_T_GEEKselectgeek0_.id as id fromT_GEEK geek0_ inner joinT_PERSON geek0_1_ on geek0_.id=geek0_1_.id wheregeek0_.FAV_PROG_LANG=?;delete
fromT_GEEK
where(id) IN (selectid fromHT_T_GEEK);delete
fromT_PERSON
where(id) IN (selectid fromHT_T_GEEK)delete
fromHT_T_GEEK;

如我们所见,Hibernate使用与我们的搜索条件匹配的极客/人员的ID填充了一个临时表。 然后,它将删除极客表中的所有行,然后删除人员表中的所有行。 最后,临时表被清除。

删除语句的顺序很明确,因为表T_GEEKT_PERSON表的id列上具有外键约束。 因此,子表中的行必须在父表中的行之前删除。 本文介绍了Hibernate创建临时表的原因。 概括起来,潜在的问题是查询限制了仅在子表中存在的列上要删除的行。 但是子表中的行必须在父表中的相应行之前删除。 删除子表中的行(即,所有具有FAV_PROG_LANG='Java'的怪胎)后,由于已经删除了怪胎行,因此无法随后删除所有对应的人员。 解决该问题的方法是临时表,该临时表首先收集应删除的所有行ID。 知道所有ID后,可以使用此信息先从怪胎表中删除行,然后从人员表中删除行。

上面生成的SQL语句当然独立于标准API的用法。 使用JPQL方法会导致生成相同的SQL:

EntityTransaction transaction = null;
try {transaction = entityManager.getTransaction();transaction.begin();int update = entityManager.createQuery("delete from Geek g where g.favouriteProgrammingLanguage = :lang").setParameter("lang", "Java").executeUpdate();LOGGER.info("Deleted " + update + " rows.");transaction.commit();
} catch (Exception e) {if (transaction != null && transaction.isActive()) {transaction.rollback();}
}

当我们将继承策略从JOINED更改为SINGLE_TABLE ,生成的SQL语句也更改为单个(此处的鉴别DTYPE列为DTYPE ):

delete
fromT_PERSON
whereDTYPE='Geek' and FAV_PROG_LANG=?

结论

用于删除和更新的标准API的新增功能使您可以构造SQL语句,而无需任何字符串连接。 但是请注意,从继承层次结构中进行批量删除可能会迫使基础ORM使用临时表,以便组装必须事先删除的行列表。

翻译自: https://www.javacodegeeks.com/2015/02/jpa-2-1-criteria-deleteupdate-temporary-tables-hibernate.html

Hibernate中的JPA 2.1条件删除/更新和临时表相关推荐

  1. Springboot中对jpa动态查询条件的封装

    jpa对于固定参数的条件查询比较简单,可以在Repository中直接用参数名来查询.但是对于不固定的参数查询就比较麻烦了,官方提供的是继承JpaSpecificationExecutor,然后自己拼 ...

  2. java中map删除指定元素_Map中根据条件删除元素

    今天在写程序过程中,需要根据判断条件删除一个Map中的相应数据,我自然而然想到可以通过调用Map中的remove(Object key)函数进行删除:代码如下: public Map processM ...

  3. java map移除_Java根据条件删除Map中元素

    今天在写程序过程中,需要根据判断条件删除一个Map中的相应数据,我自然而然想到可以通过调用Map中的remove(Object key)函数进行删除:代码如下: public Map processM ...

  4. hibernate jpa_使用Hibernate(JPA)一键式删除

    hibernate jpa 在旧版本的Hibernate中,我可以看到手册中指示的一键式删除 . 但是较新的版本不再包含此部分. 我不知道为什么. 因此,在这篇文章中,我来看看它是否仍然有效. 一键式 ...

  5. 使用Hibernate(JPA)一键式删除

    在旧版本的Hibernate中,我可以看到手册中指示的一键式删除 . 但是较新的版本不再包含此部分. 我不知道为什么. 因此,在这篇文章中,我来看看它是否仍然有效. 一键式删除部分显示: 有时一个接一 ...

  6. 表的插入、更新、删除、合并操作_17_按照条件删除表中记录

    按照条件删除表中记录 需求描述 需求:删除dept表里deptno为50的记录,但后期可通过数据库日志恢复. 解决方法:这里通过DELETE FROM TableName WHERE Columnam ...

  7. dtgrid 手动条件删除表格中的某一行

    dtgrid 手动条件删除表格中的某一行 var grid = $.fn.DtGrid.init(dtGridOption);$(function () {grid.load();});functio ...

  8. JPA+Hibernate中常用的注解

    JPA+Hibernate中常用的注解 JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体[对 ...

  9. 在Excel中怎么筛选唯一值或删除重复值以及对其应用条件格式

    重复值是行中的所有值与另一个行中的所有值完全匹配的值,筛选唯一值时,将临时隐藏重复的值,但删除重复值时,则会永久删除重复值.最好先筛选唯一值或对其应用条件格式,以便在删除重复值之前确认结果是所需的.下 ...

最新文章

  1. 【Linux网络编程笔记】TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法—实践篇
  2. ionic 混合应用开发
  3. Shell Here Document 免交互命令和Expect
  4. html5中 save方法,如何HTML5画布另存为窗口8 Metro应用中的图像文件?(How to save html5 c...
  5. 花书+吴恩达深度学习(六)优化方法之 Mini-batch(SGD, MBGD, BGD)
  6. Uninstall JavaVM and Xcode On Mac OS X
  7. 检测相关问题面试准备
  8. 微信小程序:同名在线查询系统
  9. RSSI 平面 三点定位算法(C语言、JS源码例程)
  10. 转型“系统集成商+大数据运营和服务商”,航天信息看好你哟
  11. python个税计算器代码_Python实现的个人所得税计算器示例
  12. append() 与appendTo 比较
  13. Linux下QT平台Mysql数据库开发环境配置
  14. 相位解包裹(五)枝切法(Goldstein’s branch cut algorithm)
  15. 7-2 公路村村通 迪杰斯特拉(dijkstra)算法
  16. 【latex】latex排版/overleaf在线/画图那些事
  17. 操作系统测试题(第7,8,9单元)
  18. 腾讯云 COS对象存储+视频处理总结
  19. 前端 - browserslist 的 not dead 规则是什么
  20. 安装 xilisoft Video Converter Ultimate后无法注册解决方法

热门文章

  1. spingmvc 通过xml配置redis jedispol 有密码 通过xml配置redis中的 jedispool(有密码)
  2. linux 提取cpio_15. Linux提取RPM包文件(cpio命令)详解
  3. springboot 单例_如何实现一个单例及优化
  4. Vue 媒体处理(摄像头,截图,播放本地视频)
  5. 嵌入式java基准测试_Java正则表达式库基准测试– 2015年
  6. javafx隐藏_JavaFX技巧14:StackPane子项-隐藏但不消失
  7. 如何使用Apache Camel,Quarkus和GraalVM快速运行100个骆驼
  8. λ演算的语法和语义_λ和副作用
  9. Java / Spring:如何快速生成整个Swagger记录的CRUD REST API
  10. AWS Elasticsearch后模式