Hibernate 乐观锁之Timestamp

表现

使用Timestamp类型的字段作为乐观锁的版本号,在一个事务中更新两次(save,get,update)之后,抛出OptimisticLockingFailureException异常;

解决历程

在排除了配置、事务等的原因之后,实在没有办法,引入log4jdbc,查看真正执行的SQL语句;
发现的问题是,应用中更新的时候Timestamp的值与数据库中的值会相差一秒钟,版本号不一致导致Hibernate抛出OptimisticLockingFailureException异常;

Debug查看Timestamp字段的值,发现毫秒的部分是有值的,想到MySql的Timestamp的值是精确到秒的,基本可以确认是这里的问题导致的时间不一致;

再次Debug意外发现,Hibernate在取Timestamp字段的值的时候,会将毫秒部分会四舍五入到秒;

于是查看Hibernate的文档,找一下是否有格式化时间的方案,没有找到,却发现了下面的注解

@Source


The @Source annotation is used in conjunction with a @Version timestamp entity attribute indicating the SourceType of the timestamp value.

The SourceType offers two options:

DB
Get the timestamp from the database.

VM
Get the timestamp from the current JVM.

突然想到,数据库中的Timestamp字段是自动更新的;Hibernate默认在应用中会生成基于JVM的时间值给Timestamp字段赋值,肯定是这两个时间不一致导致的;

@Version
@Column(columnDefinition="timestamp")
@Source(value = SourceType.DB)
private Timestamp ts; 

指定了Source之后,测试,发现应用中Timestamp字段的值的毫秒部分都是0了,测试通过;

原因

数据库中的Timestamp字段是自动更新的;Hibernate默认在应用中会生成基于JVM的时间值给Timestamp字段赋值,肯定是这两个时间格式不一致导致的时间值不一致,从而导致了更新的时候比较的时候,Hibernate报OptimisticLockingFailureException异常;

解决方法

使用Source注解指定时间戳的值在数据库端生成;

@Version
@Column(columnDefinition="timestamp")
@Source(value = SourceType.DB)
private Timestamp ts; 

<dependency>
	<groupId>com.googlecode.log4jdbc</groupId>
	<artifactId>log4jdbc</artifactId>
	<version>${log4jdbc.version}</version>
</dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈振阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值