2008-10-02 8 views
8

나는 Hibernate를 사용하여 데이터베이스에 매핑되는 도메인 모델을 가진 어플리케이션 A를 가지고있다. A와 정확히 같은 도메인 모델 클래스를 사용하고 몇 가지 추가 클래스를 추가하는 또 다른 응용 프로그램 B가 있습니다.Hibernate를 사용하여 한 데이터베이스에서 다른 데이터베이스로 데이터를 전송하는 방법은 무엇입니까?

제 목표는 응용 프로그램 B에서 데이터베이스 A의 데이터를 읽고 해당 데이터를 B의 데이터베이스로 전송하는 것입니다 (사본 만들기). 또한 B의 도메인 클래스 중 일부는 A의 도메인 클래스 (물론 B 데이터베이스에도 있음)와의 연관성 (OneToOne)을 가지고 있습니다.

이 작업을 수행하는 가장 좋은 전략은 무엇입니까? 나는 두 개의 세션 팩토리를 생각하고 Session.replicate()을 사용했다 (어떻게 작동 하는가?). 아니면 느슨한 커플 링을 위해이 두 도메인 모델 사이에 추가 매핑 레이어를 추가하는 것이 좋을까요?

답변

7

필자는 두 가지 다른 데이터베이스 유형 (필자의 경우 DB2와 MS SQL Server)간에 데이터를 전송하기 전에이 작업을 수행했습니다. 내가 한 것은 두 개의 분리 된 세션 팩토리를 만들고 둘 다 매핑 파일의 동일한 목록을 제공하는 것입니다. 그런 다음 한 레코드에서 레코드를 읽고 다른 레코드에 저장했습니다.

물론 두 데이터 소스가 동일하다고 가정했습니다.

+0

저는 이것을 시도하고 있지만 순환 관계에 문제가 있습니다.dest DB 제약 조건을 사용하지 못하도록 조사했지만이를 수행 할 수있는 확실한 방법을 찾지 못했습니다. 불쾌한 관계를 제거/재구성하는 데 필요한 사용자 지정 코드를 작성해야 할 수도 있습니다. –

3

복사 목적은 무엇입니까? 애플리케이션 흐름이나 로직의 일부입니까? 아니면 그냥 똑바로 데이터 복사?

데이터를 복사하기위한 것일 뿐이므로 최대 절전 모드를 사용할 필요가 없습니다. 그것을위한 많은 도구가 있습니다.

+0

예/권장 사항. 프로그래밍 방식으로 시작할 수있는 것은 무엇입니까? –

2

다른 사람들도 지적했듯이, 우리는 그것이 무엇을 성취하려고하는지 정확히 알 필요가 있다고 생각합니다. 한 번만 마이그레이션하는 경우 ETL (Extract, Transform, Load)을 수행하기 위해 Hibernate보다 좋은 도구가 있습니다.

  1. 열기 세션의 모든 개체를 읽고 데이터베이스 A.
  2. 에 :

    당신이 정말로 최대 절전 모드 (이, 또한 다니엘을 적용)에서 이렇게 주장하면, 내가 좋아하는 뭔가를 할 것 복사하려는 유형 (게으른로드가 비활성화되어 있는지 확인하십시오)

  3. 데이터베이스에 대한 세션 열기 B.
  4. 엔티티를 저장 또는 업데이트하십시오.
이 응용 프로그램 (의 기능의 일부인 경우 내가 아니라 다른 한편으로

응용 프로그램 A의 또는 B보다, 별도의 도구에서이 작업을 수행 할 것

는 예를 들어, 응용 프로그램 A는이다 관리 콘솔을 데이터에 적용하고 응용 프로그램 B는 데이터를 사용함) 상황을 조금 다르게 할 수 있습니다. 정확히 무엇을 찾고 있는지 알지 못하면 말하기가 어렵습니다.

마지막으로, (나는 이것이 당신이 찾고있는 것이라고는 생각지 않지만, 당신이 다른 방식으로 당신의 문제를 보는 것을 도울 것입니다) 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

import ca.digitalrapids.lang.GeneralException이란 무엇입니까? 어디에서나 찾을 수 없습니다. – john

+0

@john https://en.wikipedia.org/wiki/Digital_Rapids_Corporation - 이것이 독점 라이브러리 일 수 있습니까? (나는 공개적으로 이용 가능하지 않은 도서관에 의존한다면 답을 덜 유용하게 만드는 것처럼 보인다.) – EJoshuaS

+0

@EJoshua 생각합니다. 내 생각은 :이 답변은 두 upvotes있어. 즉, 최소한 두 사람이 해당 도서관이 무엇인지 알고 있으며 도서관과의 링크를 공유 할 수 있습니다. – john

관련 문제