【问题标题】: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 生成。

    【讨论】:

      猜你喜欢
      • 2012-03-13
      • 2014-09-11
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 2020-07-22
      • 1970-01-01
      • 2014-06-25
      • 2011-06-15
      相关资源
      最近更新 更多