確かに、スキーマが同じであれば、非常に簡単な方法で可能です。また、同じHibernateマッピングを使用して両方のデータベースを作成したため、Entity
では同じである必要があります。 センス。
必要なHibernate永続性ユニット(データソース)は2つだけです。両方が適切に構成されていて、特定のEntityManager
がある場合 インスタンスは便利です。HibernateのSession
に移動するだけです。 レベル-私が知る限り、JPAはこの方法でそれをサポートしていません(私が間違っている場合は訂正してください)-そしてソースエンティティをターゲットデータベースに複製します。
Springを使用するのが好きなので、次の例ではSpringBootを使用します。構成を除いて、レプリケーションステップは他のHibernateアプリケーションと同じように実装されます。
また、単純にするために、HSQLBの代わりに2つのPostgreSQLデータベースを使用しています。構成がばらばらになっている場合は、構成部分を拡張するだけです。永続化ユニット間の唯一の違いは、データソースのURLです。
したがって、最初にレプリケーションをテストするエンティティが必要です:
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
}
これは、2つのデータソース(のYAMLバージョン)の構成です(targetDatabaseUrl
と呼ばれる2番目のデータソースURLを参照してください)。 )、構成の他のすべての部分は、両方の永続性ユニットに使用されます:
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
次の部分は、データソースの構成クラスです。
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();
}
}
これで、さまざまなエンティティマネージャーを使用して、あるデータソースから別のデータソースにデータを簡単に読み書きできます。ここに小さなテストケースがあることを示すには:
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());
}
}
最後に、のいずれかを選択します。可能なレプリケーションモード ニーズに合っています。
それで全部です。トランザクションを使用することもできます。両方の永続性ユニットのいずれかを決定し、テストが@Transactional(transactionManager = "targetTransactionManager")
で行うように、そのトランザクションマネージャーを活用します。 。