我有一个更新非常频繁的类,并且我通过以下方式使用 JPA 的乐观锁定:
@Version
public long getVersion() {
return version;
}
Run Code Online (Sandbox Code Playgroud)
我看到我的测试系统上的值变得相当大,并且对生产感到紧张。JPA(我正在使用休眠)是否处理 Long.MAX_VALUE 值,或者这是我需要自己处理的事情?
谢谢,本
JPA 规范没有提及当达到版本列的最大值时将会发生什么行为。我做了一些测试来看看它的行为如何。
在Java中,Long.MAX_VALUE相当于:9223372036854775807
我使用 MySQL 作为数据库进行测试。根据MySQL文档,BIGINT映射到Java的java.util.Long类型也具有相同的最大值:9223372036854775807
在 Java 中,当您递增Long.MAX_VALUE并打印结果时,您将得到-9223372036854775808,这相当于Long.MIN_VALUE。所以我们可以说,一旦超过最大值,Java 就会循环回到最小值。MySQL 的最小值BIGINT也与 Java 的相同:-9223372036854775808
以下是我使用 JPA 进行测试的方法:
我最初TestEntity用 ff 创建了一个。代码:
@Entity
public class TestEntity implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private Long version;
private String name;
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,我首先没有用 注释版本字段@Version,因此我可以手动设置为 的最大值Long。现在,我尝试将新的内容持久保存TestEntity到 MySQL 数据库。使用以下代码:
em.getTransaction().begin();
TestEntity test = new TestEntity();
test.setName("test");
test.setVersion(Long.MAX_VALUE); // manually set the version to the maximum value
em.persist(test);
em.getTransaction().commit();
Run Code Online (Sandbox Code Playgroud)
我手动将版本字段设置为 Long 的最大值。正如 MySQL 数据库中所预期的那样,这是我从表中得到的内容:
1 | test | 9223372036854775807
Run Code Online (Sandbox Code Playgroud)
现在,我更新了TestEntity代码。这次,我用 注释了版本字段@Version。
@Entity公共类TestEntity实现可序列化{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Version
private Long version;
private String name;
...
Run Code Online (Sandbox Code Playgroud)
}
然后,我创建了一个新代码来查找TestEntity之前创建的并更新其名称:
em.getTransaction().begin();
TestEntity testEntity = em.find(TestEntity.class, 1);
testEntity.setName("changed");
em.getTransaction().commit();
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,我没有收到一条错误消息说我已达到最大值。相反,实体已成功更新。这是我的表中的内容:
1 | changed | -9223372036854775808
Run Code Online (Sandbox Code Playgroud)
你看,它确实循环回到最小值。我假设 JPA 目前没有防止达到最大值的机制。它实际上只是使用 Java 的默认行为,即在达到最大值后循环回到最小值。
| 归档时间: |
|
| 查看次数: |
573 次 |
| 最近记录: |