java获取mysql表创建时间_关于Java中集成mysql(springboot)处理数据创建时间和最后更新时间的总结...

关于Java中集成mysql(springboot)处理数据创建时间和最后更新时间的总结

​在服务端开发中,经常会遇到需要记录数据库记录的创建时间与更新时间,往常的时候只是把别人的代码粘贴过来用了,也没有实际整理过;近几天通过网上搜索及实际测试整理出一套结论

网上目前主要流传有4种解决方案,但是有一些方案确实并不合适,以下是自己整理的以下实测结果及最终推荐方案,请参考指正

1 在数据库表设计上直接解决

`createTime` datetime DEFAULT CURRENT_TIMESTAMP,

`updateTime` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

--datetime(3):括号内的数字表示保留的毫秒位数。

实测结果:

在数据库中创建一测试表,并按上述脚本建立创建时间和最后更新时间

因不推荐此方案,所以就不摆操作截图了,直说结果总结:

1.该方案在entity对象中如果不设置createTime和updateTime属性是可以的,数据库可以自动更新两个时间

2.但是在实际业务中我们很有可能会需要查询出两个时间,用于了解数据的创建和更新情况,或者用于排序;但是问题就在这里了,如果在entity对象中增加了这两个参数,并且不设置值的话,就会导致数据库中这两个字段的值为空

2 有人提出用@DynamicUpdate和@DynamicInsert

先说一下@DynamicUpdate和@DynamicInsert是干什么的,什么作用?

@DynamicInsert属性:设置为true,设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false。

比如希望数据库插入日期或时间戳字段时,在对象字段为空的情况下,表字段能自动填写当前的sysdate。

@DynamicUpdate属性:设置为true,设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中,默认false。

比如只想更新某个属性,但是却把整个对象的属性都更新了,这并不是我们希望的结果,我们希望的结果是:我更改了哪些字段,只要更新我修改的字段就够了。

举例说明

看下面打印的sql语句就会立刻明白,使用这两个注解的效果

@DynamicInsert注解下Hibernate日志打印SQL

Hibernate: insert into Cat (cat_name, id) values (?, ?)

反之

Hibernate: insert into Cat (create_time, update_time, cat_name, id) values (?, ?, ?, ?)

@DynamicUpdate注解下Hibernate日志打印SQL:

说明:如果字段有更新,Hibernate才会对该字段进行更新

Hibernate: update Cat set update_time=? where id=?

反之Cat实体类去掉@DynamicUpdate

说明:不管字段有没有更新,Hibernate都会对该字段进行更新

Hibernate: update Cat set update_time=?, cat_name=? where id=?

@MappedSuperclass 这个注解表示在父类上面的,用来标识父类。

基于代码复用和模型分离的思想,在项目开发中使用JPA的@MappedSuperclass注解将实体类的多个属性分别封装到不同的非实体类中。例如,数据库表中都需要id来表示编号,id是这些映射实体类的通用的属性,交给jpa统一生成主键id编号,那么使用一个父类来封装这些通用属性,并用@MappedSuperclas标识。

注意:

1.标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。

2.标注为@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口。

@MappedSuperclass

public abstract class BaseEntity{

@Id

@GeneratedValue

@Column(length=20)

public Integer getId() {

return this.id;

}

public void setId(Integer id) {

this.id = id;

}

}

实验结论:

​用@DynamicUpdate和@DynamicInsert实现最后更新时间其实是用了一种讨巧的方案,并且更新的时候也会存在问题;这里就不多做描述了,在此学习一下这两个注解也是很不错的

3 Spring Data JPA 的时间注解:@CreatedDate 和 @LastModifiedDate

选择 Spring Data JPA 框架开发时,常用在实体和字段上的注解有@Entity、@Id、@Column等。在表设计规范中,通常建议保留的有两个字段,一个是更新时间,一个是创建时间。Spring Data JPA 提供了相应的时间注解,只需要两步配置,就可以帮助开发者快速实现这方面的功能。

在实体类上加上注解 @EntityListeners(AuditingEntityListener.class),在相应的字段上添加对应的时间注解 @LastModifiedDate 和 @CreatedDate

注意:日期类型可以用 Date 也可以是 Long

@Entity

@EntityListeners(AuditingEntityListener.class)

public class User {

/**

* 自增主键

*/

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Integer id;

/**

* 更新时间

*/

@LastModifiedDate

@Column(nullable = false)

private Long updateTime;

/**

* 创建时间

*/

@CreatedDate

@Column(updatable = false, nullable = false)

private Date createTime;

// 省略getter和setter

2.在Application启动类中添加注解 @EnableJpaAuditing

@EnableJpaAuditing

@SpringBootApplication

public class TestApplication {

public static void main(String[] args) {

SpringApplication.run(TestApplication.class, args);

}

}

测试总结:该方案确实有效,但是配置相对繁琐;还需要在启动类上加注解

4 Hibernate 注解(最终推荐)

Hibernate 也提供了类似上述时间注解的功能实现,这种方法只需要一步配置,更改为注解 @UpdateTimestamp 和 @CreationTimestamp 即可(参考如下):

@Entity

@Table(name = "java2mysql")

@Data

public class Java2Mysql implements Serializable {

private static final long serialVersionUID = -1L;

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private int id;

@Column(name = "name")

private String name;

@Column(name = "update_time")

@Temporal(TemporalType.TIMESTAMP)

@UpdateTimestamp

private Date updateTime;

@Column(name = "create_time",updatable = false)

@Temporal(TemporalType.TIMESTAMP)

@CreationTimestamp

private Date createTime;

在此补充两个注解的解释

@Column

# @Column注解

用来标识实体类中属性与数据表中字段的对应关系

# 属性详解:

name

定义了被标注字段在数据库表中所对应字段的名称;

unique

表示该字段是否为唯一标识,默认为false。如果表中有一个字段需要唯一标识,则既可以使用该标记,也可以使用@Table标记中的@UniqueConstraint。

nullable

表示该字段是否可以为null值,默认为true。

insertable

表示在使用“INSERT”脚本插入数据时,是否需要插入该字段的值。

updatable

表示在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值。insertable和updatable属性一般多用于只读的属性,例如主键和外键等。这些字段的值通常是自动生成的。

columnDefinition(大多数情况,几乎不用)

表示创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用。(也就是说,如果DB中表已经建好,该属性没有必要使用。)

table

表示当映射多个表时,指定表的表中的字段。默认值为主表的表名。

length

表示字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符。

precision和scale

precision属性和scale属性表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数。

# @Column可以标注在属性前或getter方法前

@Column标注在属性前(建议使用这一种方式)

@Temporal

数据库的字段类型有date、time、datetime

而Temporal注解的作用就是帮Java的Date类型进行格式化,一共有三种注解值:

第一种:@Temporal(TemporalType.DATE)——>实体类会封装成日期“yyyy-MM-dd”的 Date类型。

第二种:@Temporal(TemporalType.TIME)——>实体类会封装成时间“hh-MM-ss”的 Date类型。

第三种:@Temporal(TemporalType.TIMESTAMP)——>实体类会封装成完整的时间“yyyy-MM-dd hh:MM:ss”的 Date类型。

注解方式有两种:

写在字段上:

@Temporal(TemporalType.TIMESTAMP)

private Date birthday;

写在 getXxx方法上:

@Temporal(TemporalType.DATE)

@Column(name = "birthday", length = 10)

public Date getBirthday() {

return this.birthday;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值