2008-10-02 57 views
8

我有一個應用程序A和一個使用Hibernate映射到數據庫的域模型。我有另一個應用程序B使用完全相同的領域模型類作爲A並添加一些額外的類。如何使用Hibernate將數據從一個數據庫傳輸到另一個數據庫?

我的目標是從應用程序B中的數據庫A中讀取數據,並將該數據傳輸到B的數據庫中(以製作它的副本)。另外,B的一些域類具有與A的域類(但當然在B的數據庫中)的關聯(OneToOne)。

完成此操作的最佳策略是什麼?我想到了兩個會話工廠,並使用Session.replicate()(這是如何工作的?)。或者我應該更好地在這兩個領域模型之間引入一個額外的映射層以實現鬆散耦合?

回答

7

我以前在兩種不同的數據庫類型(在本例中是DB2和MS SQL Server)之間傳輸數據。我所做的就是創建兩個單獨的會話工廠,併爲它們提供相同的映射文件列表。然後,我只是從一個記錄中讀取記錄,並將它們保存到另一個。

當然,這假定兩個數據源是相同的。

+0

我正在嘗試這個,但遇到了循環關係的問題。調查禁用dest DB約束,但找不到一個明顯的方法來做到這一點。可能必須編寫自定義代碼來刪除/重建違規關係。 – 2012-09-27 15:55:31

3

複製的目的是什麼?這是你的應用程序流程或邏輯的一部分嗎?或只是直接進行數據複製?

如果僅僅是爲了複製數據而沒有必要使用休眠。有很多的工具。

+0

請舉例/建議。任何可以以編程方式啓動的東西? – 2012-09-27 15:56:47

2

像其他人一樣指出,我認爲我們需要確切知道你想要達到的目標。如果你正在做一次遷移,那麼比Hibernate有更好的工具來完成ETL(提取,轉換,加載)。

如果你真的堅持在休眠(這適用於您還丹尼爾)這樣做,我會做一些事情,如:

  1. 公開會議,數據庫A.
  2. 閱讀的所有實體請確保延遲加載被禁用
  3. 打開會話到數據庫B.
  4. 保存或更新實體。

我應該這樣做在一個單獨的工具,而不是在應用程序A或B.

在另一方面,如果這是你的應用程序(部分功能如應用A是管理控制檯添加到數據中,而應用程序B則使用這些數據),您可能希望做的事情稍有不同。很難說不知道你在找什麼。 Hibernate Shards(http://shards.hibernate.org/)。最後,有些東西需要研究(我不認爲這是你要找的東西,但也許它會幫助你以不同的方式看待你的問題)是Hibernate Shards(http://shards.hibernate.org/)。

2

嘗試了其他工具,並有問題。這是我的家庭解決方案。可能需要一些清理,但它的肉在那裏。

import java.io.Serializable; 
import java.util.List; 
import java.util.logging.Logger; 

import lombok.Getter; 
import lombok.RequiredArgsConstructor; 
import lombok.Setter; 

import org.hibernate.Session; 
import org.hibernate.Transaction; 

import ca.digitalrapids.lang.GeneralException; 
import ca.digitalrapids.mediamanager.server.dao.hibernate.GenericDAOHibernate; 
import ca.digitalrapids.mediamanager.server.dao.hibernate.GenericDAOHibernate.GenericDAOHibernateFactory; 
import ca.digitalrapids.persist.dao.DAOOptions; 
import ca.digitalrapids.persist.hibernate.HibernateUtil2; 

import com.google.common.collect.ImmutableMultimap; 
import com.google.common.collect.ImmutableSet; 
import com.google.common.collect.Sets; 

@RequiredArgsConstructor 
public class DataMigrator 
{ 
    private static final Logger logger = Logger 
     .getLogger(DataMigrator.class.getName()); 
    private final HibernateUtil2 sourceHibernateUtil2; 
    private final HibernateUtil2 destHibernateUtil2; 
    private final ImmutableSet<Class<?>> beanClassesToMigrate; 
    @Setter @Getter 
    private Integer copyBatchSize = 10; 
    @Setter 
    private GenericDAOHibernateFactory sourceDaoFactory = 
     new GenericDAOHibernate.GenericDAOHibernateFactoryImpl(); 
    @Setter 
    private GenericDAOHibernateFactory destDaoFactory = 
     new GenericDAOHibernate.GenericDAOHibernateFactoryImpl(); 
    private final ImmutableMultimap<Class<?>, Class<?>> entityDependencies; 

    public void run() throws GeneralException 
    { 
     migrateData(sourceHibernateUtil2.getSession(), 
      destHibernateUtil2.getSession()); 
    } 

    private void migrateData(Session sourceSession, Session destSession) 
     throws GeneralException 
    { 
     logger.info("\nMigrating data from old HSQLDB database.\n"); 

     Transaction destTransaction = null; 
     try 
     { 
      destTransaction = destSession.beginTransaction(); 
      migrateBeans(sourceSession, destSession, beanClassesToMigrate, 
       entityDependencies); 
      destTransaction.commit(); 
     } catch (Throwable e) { 
      if (destTransaction != null) 
       destTransaction.rollback(); 
      throw e; 
     } 

     logger.info("\nData migration complete!\n"); 
    } 



    private void migrateBeans(Session sourceSession, Session destSession, 
     ImmutableSet<Class<?>> beanClasses, ImmutableMultimap<Class<?>, Class<?>> deps) 
    { 
     if (beanClasses.isEmpty()) return; 
     Class<?> head = beanClasses.iterator().next(); 
     ImmutableSet<Class<?>> tail = 
      Sets.difference(beanClasses, ImmutableSet.of(head)).immutableCopy(); 
     ImmutableSet<Class<?>> childrenOfHead = getChildren(head, tail, deps); 
     migrateBeans(sourceSession, destSession, childrenOfHead, deps); 
     migrateBean(sourceSession, destSession, head); 
     migrateBeans(sourceSession, destSession, 
      Sets.difference(tail, childrenOfHead).immutableCopy(), deps); 
    } 

    private ImmutableSet<Class<?>> getChildren(Class<?> parent, 
     ImmutableSet<Class<?>> possibleChildren, 
     ImmutableMultimap<Class<?>, Class<?>> deps) 
    { 
     ImmutableSet<Class<?>> parentDeps = ImmutableSet.copyOf(deps.get(parent)); 
     return Sets.intersection(possibleChildren, parentDeps).immutableCopy(); 
    } 

    private void migrateBean(Session sourceSession, Session destSession, 
     Class<?> beanClass) 
    { 
     GenericDAOHibernate<?, Serializable> sourceDao = 
      sourceDaoFactory.get(beanClass, sourceSession); 
     logger.info("Migrating "+sourceDao.countAll()+" of "+beanClass); 

     DAOOptions options = new DAOOptions(); 
     options.setMaxResults(copyBatchSize); 
     List<?> sourceBeans; 
     int firstResult = 0; 
     int sourceBeansSize; 
     do { 
      options.setFirstResult(firstResult); 
      sourceBeans = sourceDao.findAll(options); 
      sourceBeansSize = sourceBeans.size(); 
      @SuppressWarnings("unchecked") 
      GenericDAOHibernate<Object, Serializable> destDao = 
       (GenericDAOHibernate<Object, Serializable>) 
       destDaoFactory.get(beanClass, destSession); 
      for (Object sourceBean : sourceBeans) 
      { 
       destDao.save(sourceBean); 
      } 
      firstResult += copyBatchSize; 
      sourceSession.clear();/* prevent memory problems */ 
     } while (sourceBeansSize >= copyBatchSize); 
    } 
} 
+2

什麼是導入ca.digitalrapids.lang.GeneralException?無法在任何地方找到 – john 2017-01-09 23:16:19

相關問題