Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Kopiuj dane między różnymi bazami danych (obie są obsługiwane przez jdbc)

Jasne, jest to możliwe w bardzo prosty sposób, jeśli schematy są takie same. A ponieważ utworzyłeś obie bazy danych z tym samym mapowaniem Hibernate, powinny one być równe w Entity sens.

Potrzebujesz tylko dwóch jednostek trwałości Hibernate (źródła danych). Jeśli oba są poprawnie skonfigurowane i masz konkretnego EntityManager przydatne instancje, po prostu przejdź do Session Hibernacji poziom - o ile wiem, JPA nie obsługuje tego w ten sposób (popraw mnie, jeśli się mylę) - i zreplikuj swoją encję źródłową do docelowej bazy danych.

Ponieważ lubię pracować ze Springiem, w poniższym przykładzie użyję Spring Boot. Z wyjątkiem konfiguracji, krok replikacji byłby zaimplementowany tak samo w dowolnej aplikacji Hibernate.

Używam również dwóch baz danych PostgreSQL zamiast HSQLB tylko po to, aby było to proste. Po prostu rozszerz część konfiguracyjną, jeśli twoje konfiguracje się rozchodzą, jedyną różnicą między moimi jednostkami trwałości jest adres URL źródła danych.

Więc najpierw potrzebujemy encji do przetestowania replikacji:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class StorageEntry {

    @Id
    @GeneratedValue
    private Long id;

    private String someValue;

    // imagine getters and setter here

}

To jest (wersja YAML) konfiguracja dwóch źródeł danych (zobacz drugi adres URL źródła danych o nazwie targetDatabaseUrl ), Wszystkie pozostałe części konfiguracji zostaną użyte dla obu jednostek trwałości:

spring:
  datasource:
    url: jdbc:postgresql://localhost/postgres
    targetDatabaseUrl: jdbc:postgresql://localhost/postgres2
    username: <username>
    password: <password>
    driver-class-name: org.postgresql.Driver
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    hibernate:
      ddl-auto: create-drop

Następna część to klasa konfiguracyjna dla źródeł danych:

import java.util.Properties;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class PersistenceConfig {

    @Autowired
    private JpaVendorAdapter jpaVendorAdapter;

    @Value("${spring.datasource.url}")
    private String databaseUrl;

    @Value("${spring.datasource.targetDatabaseUrl}")
    private String targetDatabaseUrl;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.jpa.database-platform}")
    private String dialect;

    @Value("${spring.jpa.hibernate.ddl-auto}")
    private String ddlAuto;

    @Bean
    public EntityManager sourceEntityManager() {
        return sourceEntityManagerFactory().createEntityManager();
    }

    @Bean
    public EntityManager targetEntityManager() {
        return targetEntityManagerFactory().createEntityManager();
    }

    @Bean
    public EntityManagerFactory sourceEntityManagerFactory() {
        return createEntityManagerFactory("source", databaseUrl);
    }

    @Bean
    public EntityManagerFactory targetEntityManagerFactory() {
        return createEntityManagerFactory("target", targetDatabaseUrl);
    }

    @Bean
    public PlatformTransactionManager sourceTransactionManager() {
        return new JpaTransactionManager(sourceEntityManagerFactory());
    }

    @Bean
    public PlatformTransactionManager targetTransactionManager() {
        return new JpaTransactionManager(targetEntityManagerFactory());
    }

    private EntityManagerFactory createEntityManagerFactory(final String persistenceUnitName,
            final String databaseUrl) {
        final LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

        final DriverManagerDataSource dataSource = new DriverManagerDataSource(databaseUrl, username, password);
        dataSource.setDriverClassName(driverClassName);
        entityManagerFactory.setDataSource(dataSource);

        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
        entityManagerFactory.setPackagesToScan("com.example.model");
        entityManagerFactory.setPersistenceUnitName(persistenceUnitName);

        final Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", dialect);
        properties.setProperty("hibernate.hbm2ddl.auto", ddlAuto);
        entityManagerFactory.setJpaProperties(properties);

        entityManagerFactory.afterPropertiesSet();
        return entityManagerFactory.getObject();
    }

}

Teraz możesz używać różnych menedżerów encji, aby po prostu odczytywać i zapisywać dane z jednego źródła danych do drugiego. Aby pokazać, że oto mały przypadek testowy:

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import com.example.model.StorageEntry;

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional(transactionManager = "targetTransactionManager")
public class ReplicationTests {

    @PersistenceContext(unitName = "source")
    private EntityManager sourceEntityManager;

    @PersistenceContext(unitName = "target")
    private EntityManager targetEntityManager;

    @Test
    public void copyEntityBetweenPersistenceUnits() {
        final StorageEntry entityToCopy = new StorageEntry();
        entityToCopy.setSomeValue("copyMe!");
        sourceEntityManager.persist(entityToCopy);

        final Long id = entityToCopy.getId();

        final StorageEntry sourceEntity = sourceEntityManager.find(StorageEntry.class, id);
        assertThat("Entity should exist in default schema!", sourceEntity, notNullValue());

        StorageEntry targetEntity = targetEntityManager.find(StorageEntry.class, id);
        assertThat("Target schema should not contain the entity, yet!", targetEntity, nullValue());

        final Session hibernateSession = targetEntityManager.unwrap(Session.class);
        hibernateSession.replicate(sourceEntity, ReplicationMode.OVERWRITE);

        targetEntityManager.flush();
        targetEntityManager.clear();

        targetEntity = targetEntityManager.find(StorageEntry.class, id);
        assertThat("Entity should be copied now!", targetEntity, notNullValue());
    }

}

Na koniec wybierz jeden z możliwe tryby replikacji który odpowiada Twoim potrzebom.

To wszystko. Możesz nawet użyć transakcji, po prostu zdecyduj się na jedną z obu jednostek trwałości i wykorzystaj jej menedżera transakcji, tak jak robi to test z @Transactional(transactionManager = "targetTransactionManager") .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Automatyczne inkrementowanie mysql ID nie zaczyna się od 0

  2. MySql — Sequalize — Nie można dodać ograniczenia klucza obcego

  3. mysql sortowanie i zestawienie rankingowe

  4. Czy należy używać wartości NULL lub pustego ciągu do reprezentowania żadnych danych w kolumnie tabeli?

  5. PostgreSQL GROUP BY różni się od MySQL?