休眠将对象保存到多个会话

2022-09-04 03:41:25

我正在尝试使用休眠写入多个数据库。我已将写入和读/写会话封装在单个会话对象中。但是,当我去保存时,我收到了很多错误,即对象已经与另一个会话相关联:“非法尝试将集合与两个打开的会话相关联”

这是我的代码:

public class MultiSessionObject implements Session {

       private Session writeOnlySession;
       private Session readWriteSession;

       @Override
       public void saveOrUpdate(Object arg0) throws HibernateException {
              readWriteSession.saveOrUpdate(arg0);
              writeOnlySession.saveOrUpdate(arg0);
       }
}

我尝试过驱逐物体并冲洗;但是,这会导致“行被另一个事务更新或删除”的问题...即使两个会话都指向不同的数据库。

public class MultiSessionObject implements Session {

       private Session writeOnlySession;
       private Session readWriteSession;

       @Override
       public void saveOrUpdate(Object arg0) throws HibernateException {
              readWriteSession.saveOrUpdate(arg0);
              readWriteSession.flush();
              readWriteSession.evict(arg0);

              writeOnlySession.saveOrUpdate(arg0);
              writeOnlySession.flush();
              writeOnlySession.evict(arg0);
       }
}

除了上述之外,我还尝试使用休眠的复制功能。这也是不成功的,没有错误。

是否有人成功地将对象保存到具有相同架构的两个数据库中?


答案 1

尝试将给定实体重新附加到当前正在运行的会话,因此代理(LAZY 关联)绑定到休眠会话。请尝试使用 merge 而不是 saveOrUpdate,因为只需将分离的实体状态复制到新检索到的托管实体即可。这样,提供的参数永远不会附加到会话。saveOrUpdatemerge

另一个问题是事务管理。如果使用线程绑定事务,则如果要从同一线程更新两个数据源,则需要两个显式事务。

尝试也显式设置事务边界:

public class MultiSessionObject implements Session {

   private Session writeOnlySession;
   private Session readWriteSession;

   @Override
   public void saveOrUpdate(Object arg0) throws HibernateException {

        Transaction readWriteSessionTx = null;
        try {
            readWriteSessionTx = readWriteSession.beginTransaction();
            readWriteSession.merge(arg0);
            readWriteSessionTx.commit();
        } catch (RuntimeException e) {
            if ( readWriteSessionTx != null && readWriteSessionTx.isActive() ) 
                readWriteSessionTx.rollback();
            throw e;
        }

        Transaction writeOnlySessionTx = null;
        try {
            writeOnlySessionTx = writeOnlySession.beginTransaction();
            writeOnlySession.merge(arg0);
            writeOnlySessionTx.commit();
        } catch (RuntimeException e) {
            if ( writeOnlySessionTx != null && writeOnlySessionTx.isActive() ) 
                writeOnlySessionTx.rollback();
            throw e;
        }
   }
}

答案 2

如其他答案中所述,如果您正在使用,则可能需要将2个更新分开,并在两个不同的事务中。实体的分离实例(之后)应该能够在第二次更新操作中重用。Sessionevict

另一种方法是像这样使用(我尝试了一个简单的程序,所以必须处理交易。我假设你必须以不同的方式处理交易)StatelessSession

public static void main(final String[] args) throws Exception {
        final StatelessSession session1 = HibernateUtil.getReadOnlySessionFactory().openStatelessSession();
        final StatelessSession session2 = HibernateUtil.getReadWriteSessionFactory().openStatelessSession();
        try {
            Transaction transaction1 = session1.beginTransaction();
            Transaction transaction2 = session2.beginTransaction();
            ErrorLogEntity entity = (ErrorLogEntity) session1.get(ErrorLogEntity.class, 1);
            entity.setArea("test");
            session1.update(entity);
            session2.update(entity);
            transaction1.commit();
            transaction2.commit();
            System.out.println("Entry details: " + entity);
        } finally {
            session1.close();
            session2.close();
            HibernateUtil.getReadOnlySessionFactory().close();
            HibernateUtil.getReadWriteSessionFactory().close();
        }
    }

问题是它不使用任何缓存,并且不支持关联对象的级联。您需要手动处理。StatelessSession


推荐