【问题标题】:Hibernate reset sequence cacheHibernate 重置序列缓存
【发布时间】:2023-01-13 05:04:39
【问题描述】:
例子:
- 假设实体E有序列e_seq生成的id
- 假设数据库中sequence的值初始为0,increment配置为50
- 当休眠启动时,它获取序列的下一个值(即 0+50=50)并保留可用值的内部缓存(即 0-50 区间内的值)
- 只要缓存有可用值,就不会再向 dbms 发出请求以获取序列的下一个值
- 只有在您创建实体 E 的 50 个实例后,才会使用 50 个 ID,并且休眠会向 dbms 询问下一个值。
- 假设 hibernate 缓存还有 50 个 ids 可用
- 假设一个低级过程(如数据迁移)使用 SQL 语句(不使用休眠 API)在数据库中插入 100 个类型为 E 的实体,id 从 1 到 100,然后将序列值重置为 100
- 如果应用程序尝试从其 API 创建新实体,它将使用从休眠缓存中获取的 ID,但该 ID 已被低级过程使用,因此导致重复 ID 异常
因此,我需要找到一种方法来告诉 Hibernate“重置其 ids 缓存”,或者换句话说“强制 hibernate 再次联系 dbms 以获取当前序列值”。
【问题讨论】:
标签:
java
database
hibernate
【解决方案1】:
(注意:只是一个想法......)
你可以试试
@GenericGenerator(name="wrapped_sequence", "strategy"="com.package.WrappedSequenceGenerator")
@GeneratedValue(generator = "wrapped_sequence")
课程可能是:
public class WrappedSequenceGenerator implements IdentifierGenerator {
/* or extends SequenceStyleGenerator and then look at SequenceStructure, to get a more "Hibernate-friendly" solution */
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
Connection conn = this.connection();
Serializable id ;
// here you create a Statement to execute the code to return the original sequence value
// e.g. (ORACLE syntax) execute a stmt like "select my_sequence.nextval from dual"
// and extract the result into "id"
return id;
}
}
}
当然,付出的代价是在 Hibernate 应用程序中更慢的 id 生成。