关于@DynamicUpdate的误解

先看证据


二话不说,先把@DynamicUpdate的官方api-doc呈出来(以下图),参见https://docs.jboss.org/hibernate/stable/orm/javadocs/ 前端

翻译成白话文:

  • 对于更新,此实体是否应在使用动态sql生成时,仅在预处理sql语句中引用已更改的列。
  • 请注意,对于从新附加分离的实体,若是未启用select-before-update,则没法执行此操做。

举栗子


先说明一下@DynamicUpdate注解用在实体类上java

有数据库表tbl_foo和对应的实体类Foo,以下:web

id name col3 col4 col5
1 毕加索 1770 奥地利
class Foo{
    private Integer id;
    private String name;
    private String col3;
    private String col4;
    private String col5;
    getter...
    setter...
}
复制代码

在Service中更新id=1记录的name属性,代码以下:sql

Foo foo = fooDao.findById(1);
foo.setName("贝多芬");
fooDao.save(foo);
复制代码

两种状况:数据库

  1. 在entity类中未使用@DynamicUpdate注解或使用了@DynamicUpdate(false),那么Hibernate底层执行的sql如:
update tbl_foo set name=?, col3=?, col4=?, col5=? where id=?
复制代码
  1. 在entity类中使用了@DynamicUpdate注解(或@DynamicUpdate(true)),Hibernate底层执行的sql如:
update tbl_foo set name=? where id=?
复制代码

以上两种状况对数据库更新的结果是等效的,可是使用@DynamicUpdate性能会好一些。由于不使用@DynamicUpdate时,即便没有改变的字段也会被更新。若是进行频繁的更新操做,而且每次只更新少数字段,那么@DynamicUpdate对性能的优化效果仍是很好的。api

误解


咱们常有一种需求,web层用对象接收前端要修改的属性值(不修改的值为空),咱们但愿直接调用dao的update方法进行选择更新。性能

web层使用对象接收前端要修改的属性值,可等效看作执行以下代码:学习

Foo foo = new Foo();
foo.setId(1);
foo.setName("贝多芬");
复制代码

这时服务层直接使用这个对象进行更新优化

fooDao.update(foo);
复制代码

咱们期待的结果:spa

id name col3 col4 col5
1 贝多芬 1770 奥地利

看到网上有些文章说在实体类加上@DynamicUpdate,就能够知足咱们的以上需求,可是很遗憾,否则!

反而获得这样的结果是:

id name col3 col4 col5
1 贝多芬

只要彻底理解了api-doc中对@DynamicUpdat的说明,就很容易知道获得这个结果的缘由了。@DynamicUpdate的动态更新的含义是,比较更新要使用的实体类中的字段值与从数据库中查询出来的字段值,判断其是否有修改。看这个例子,数据库中id=1的记录全部字段都是非空的,可是实体类中只有name有值,也就是全部字段都变了,只是其余字段被更新为了新的空值。

闲言碎语(一些废话能够忽略)


  • 学习一个注解(或者类)的用法,无论是开源的仍是商业的,最简单、最靠谱、最直接的途径就是一手的官方api文档。

  • 有些小哥哥在使用Spring Data JPA时用到了@DynamicUpdate,就理算固然的认为它和Spring是一家,其实否则。其实从引用注解时的包名就能看出来,很明显Hibernate才是它的原配。缘由固然就是Spring Data JPA使用的ORM实现是Hibernate。因此也就解释了上图中的文档是Hibernate的api文档,而不是Spring或者Java的api文档。

以上所有为我的观点,但愿对你有帮助。本人水平有限,不免有不妥或者谬误之处,望你们指出。有其余问题也欢迎和你们交流!

相关文章
相关标签/搜索