天天看点

spring-data-jpa进行更新时无法根据系统当前时间更新update_time || @DynamicUpdate和@DynamicInsert的作用

自从mysql5.7之后,相信大家在设计数据库的时间字段时都会设计成下面这样达到自动更新的效果,非常实用。

`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
           

 但是,今天在使用jpa进行更新操作的时候,却发现update_time并没有自动更新,在多次尝试之后才发现如果需要自动更新update_time,需要在jpa对于的实体类上加上@DynamicUpdate注解才可以,于是也深入研究了下这个注解,发现这个注解还有其他的作用,例如它可以提高访问数据库的效率,那么它是怎么做到的呢?下面会具体演示分析。

1. 首先我们在实体类上不加@DynamicUpdate注解进行测试。

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategory {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Integer categoryId;
    private String categoryName;
    private String categoryType;
    private Date createTime;
    private Date updateTime;
}
           
@Test
   public void updateTest() {
       ProductCategory one = productCategotyJpaRepository.findById(1).get();
       one.setCategoryName("测试");
       productCategotyJpaRepository.save(one);
   }
           
控制台打印信息:
Hibernate: update product_category set category_name=?, category_type=?, create_time=?, update_time=? where category_id=?
           

 小结:实际上我们只更新了一个类别名称字段,但是从控制台打印的sql可以看出,jpa更新了所有的字段,字段值没有改变的它也去update了,这是非常消耗性能的操作。

2.我们加上@DynamicUpdate注解后再次进行测试

@Entity
@DynamicUpdate
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategory {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Integer categoryId;
    private String categoryName;
    private String categoryType;
    private Date createTime;
    private Date updateTime;
}
           
@Test
    public void updateTest() {
        ProductCategory one = productCategotyJpaRepository.findById(1).get();
        one.setCategoryName("测试2");
        productCategotyJpaRepository.save(one);
    }
           
控制台打印信息:
Hibernate: update product_category set category_name=? where category_id=?
           

小结:我们会发现加上了@DynamicUpdate注解之后,jpa会自动识别字段值有改动的,然后选择性的进行更新操作,提高了执行效率。

番外篇:我们点进这个注解的源码会发现,@DynamicUpdate默认值是true,@DynamicUpdate(false)和不加是同等效果。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicUpdate {
    boolean value() default true;
}
           

总结:

1.使用jpa时,如果需要设置数据库时间为自动更新,需要配合@DynamicUpdate才能生效,但是新增的时候不需要加@DynamicInsert也可以生效。

[email protected]可以自动识别值发生变化的字段,只update这些字段,提高访问数据库的效率,@DynamicInsert同理。

3.使用jpa的时候最好加上@DynamicUpdate,@DynamicInsert这2个注解。