9

我有一个带有域模型的应用程序 A,它使用 Hibernate 映射到数据库。我有另一个应用程序 B,它使用与 A 完全相同的域模型类,并添加了一些额外的类。

我的目标是从应用程序 B 中的数据库 A 读取数据并将该数据传输到 B 的数据库中(以制作它的副本)。此外,B 的一些域类与 A 的域类有关联(OneToOne)(当然是在 B 的数据库中)。

实现这一目标的最佳策略是什么?我想到了两个会话工厂并使用Session.replicate()(这是如何工作的?)。或者我应该更好地在这两个域模型之间引入一个额外的映射层以实现松散耦合?

4

4 回答 4

8

我之前已经这样做了,以便在两种不同的数据库类型(在我的例子中是 DB2 和 MS SQL Server)之间传输数据。我所做的是创建两个单独的会话工厂,并为它们提供相同的映射文件列表。然后我只是从一个读取记录,并将它们保存到另一个。

当然,这假设两个数据源是相同的。

于 2008-10-06T20:21:09.483 回答
4

抄袭的目的是什么?那是您的应用程序流程或逻辑的一部分吗?还是直接复制数据?

如果只是为了拷贝数据过来,就没有必要使用hibernate了。有很多工具可以做到这一点。

于 2008-10-03T01:43:43.260 回答
2

就像其他人指出的那样,我认为我们需要确切地知道你想要完成什么。如果您正在进行一次性迁移,那么有比 Hibernate 更好的工具来执行 ETL(提取、转换、加载)。

如果您真的坚持在 Hibernate 中执行此操作(这也适用于您,Daniel),我会执行以下操作:

  1. 打开数据库 A 的会话。
  2. 读取您尝试复制的类型的所有实体(确保禁用延迟加载)
  3. 打开到数据库 B 的会话。
  4. 保存或更新实体。

我会在单独的工具中执行此操作,而不是在应用程序 A 或 B 中。

另一方面,如果这是您的应用程序功能的一部分(例如,应用程序 A 是数据的管理控制台,而应用程序 B 使用数据),您可能希望做一些不同的事情。如果不知道您到底在寻找什么,就很难说。

最后,要研究的东西(我认为这不是您要寻找的,但也许它会帮助您以不同的方式看待问题)是 Hibernate Shards ( http://shards.hibernate.org /)。

于 2008-10-31T15:04:44.330 回答
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 );
    }
}
于 2012-09-28T06:14:03.213 回答