2008-10-02 94 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

相关问题