hibernate 休眠复位序列缓存

3okqufwl  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(117)
    • bounty将在6天后过期**。回答此问题可获得+50声望奖励。Oleksandr Riznyk希望引起更多人关注此问题。

示例:

  • 假设实体E具有由定序器e_seq生成id
  • 假设数据库中sequence初始值为0,increment配置为50
  • 当休眠启动时,它获取序列的下一个值(即0 + 50 = 50),并保持可用值的内部缓存(即0 - 50区间内的值)
  • 只要高速缓存有可用的值,就不再向数据库管理系统请求序列的下一个值
  • 只有在创建了实体E的50个示例之后,50个id才被使用,并且hib向dbms询问下一个值。
  • 假设休眠高速缓存仍然有50个ID可用
  • 假设一个低级过程(如数据迁移)使用SQL语句(不使用Hibernate API)在数据库中插入100个类型为E的实体,id从1到100,然后将序列值重置为100
  • 如果应用程序尝试从其API创建新实体,则它将使用从休眠缓存中获取的ID,但该ID已经被低级过程使用,因此导致重复ID异常

因此,我需要找到一种方法来告诉Hibernate "重置它的ID缓存",或者换句话说,"强制Hibernate再次联系DBMS以获取当前的序列值"。

gt0wga4j

gt0wga4j1#

您是否尝试过清除当前会话并创建一个新会话?这会迫使Hibernate重新查询数据库以获取当前序列值。
换句话说,您可以使用Session.flush()Session.clear()方法:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

// Perform some operations that use the id cache

session.flush();
session.clear();

// Perform some more operations that use the id cache

transaction.commit();
session.close();

或者您可以使用EntityManager.refresh(),它将刷新数据库中示例的状态,并在此过程中使用当前序列值更新内部缓存:

EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();

// Perform some operations that use the id cache

em.refresh(entity);

// Perform some more operations that use the id cache

em.getTransaction().commit();
em.close();

相关问题