복붙노트

[SPRING] Spring에서 여러 데이터베이스 초기화하기

SPRING

Spring에서 여러 데이터베이스 초기화하기

AbstractRoutingDatasource를 사용하여 런타임 중에 데이터베이스 사이를 경로 지정합니다. informix 데이터베이스의 실제 상황에서는 모든 것이 잘 작동합니다.

테스트를 위해 메모리 H2 데이터베이스에 사용할 스프링 프로파일을 만들었습니다. 테스트 프로파일을 사용하여 스프링 애플리케이션을 실행 한 후 h2 콘솔을 사용하여 로컬 데이터베이스를 점검했습니다. 스키마가 작성되지 않았습니다.

나는 자원과 최대 절전 모드에서 schema.sql을 사용했다.

generate-ddl: true
hibernate:
  ddl-auto: create-drop

최대 절전 모드

java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [null]

hibernate ist가 "라우팅 된"데이터 소스 만 생성하려고한다는 것을 이해하고 있습니다. DatabaseContextHolder가 설정되어 있지 않기 때문에 (null), 실패합니다.

따라서 두 가지 방법 모두 실패합니다.

(동일한) 스키마로 모든 데이터베이스를 초기화하는 방법이 있습니까?

아래에 구성을 나열합니다.

bootstrap.yml :

spring:
  profiles: acceptanceTest
  config:
    name: standalone
  cloud:
    config:
      enabled: false
      discovery:
        enabled: false
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    generate-ddl: true
    hibernate:
      ddl-auto: create-drop
    properties:
      hibernate:
        show_sql: false
        use_sql_comments: false
        format_sql: false
  h2:
    console:
      enabled: true
      path: /h2
datasource:
  mc:
    driver-class-name: 'org.h2.Driver'
    url: 'jdbc:h2:mem:test-mc-db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
    username: sa
    password: ''
    platform: h2
    initialize: true
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      maximum-pool-size: 10
      minimum-idle: 0
      idle-timeout: 60000
      pool-name: MarkHikariPool
  cw:
    driver-class-name: 'org.h2.Driver'
    url: 'jdbc:h2:mem:test-cw-db'
    username: sa
    password: ''
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      maximum-pool-size: 10
      minimum-idle: 0
      idle-timeout: 60000
      pool-name: MarkHikariPool

MainApp.java:

@ComponentScan({ "de.md.mark" })
@EnableDiscoveryClient
@SpringBootApplication(
    exclude =
        {
            DataSourceAutoConfiguration.class,
            DataSourceTransactionManagerAutoConfiguration.class,
            HibernateJpaAutoConfiguration.class
        }
)
public class MainApp
{
    public static void main(String[] args)
    {

DataSourceConfiguration.java:

@Configuration
@EnableJpaRepositories(
    basePackageClasses = { MarkTypeRepository.class, MarkRepository.class }, entityManagerFactoryRef = "markEntityManager",
    transactionManagerRef = "markTransactionManager"
)
@EnableTransactionManagement
public class DataSourceConfiguration
{
    @Autowired(required = false)
    private PersistenceUnitManager persistenceUnitManager;

    @Bean
    @ConfigurationProperties("app.jpa")
    @Primary
    public JpaProperties jpaProperties()
    {
        return new JpaProperties();
    }

    @Bean
    @ConfigurationProperties(prefix = "datasource.mc")
    public DataSource mcDataSource()
    {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "datasource.cw")
    public DataSource cwDataSource()
    {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource dataSource()
    {
        DataSourceRouter router = new DataSourceRouter();

        final HashMap<Object, Object> map = new HashMap<>(DatabaseEnvironment.values().length);
        map.put(DatabaseEnvironment.MC, mcDataSource());
        map.put(DatabaseEnvironment.CW, cwDataSource());
        router.setTargetDataSources(map);
        return router;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean markEntityManager(final JpaProperties jpaProperties)
    {
        EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(jpaProperties);

        return builder.dataSource(dataSource()).packages(MarkTypeEntity.class).persistenceUnit("markEntityManager").build();
    }

    @Bean
    @Primary
    public JpaTransactionManager markTransactionManager(@Qualifier("markEntityManager") final EntityManagerFactory factory)
    {
        return new JpaTransactionManager(factory);
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties)
    {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
        return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), this.persistenceUnitManager);
    }

    private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties)
    {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.getDatabase());
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
        return adapter;
    }
}

해결법

  1. ==============================

    1.지난 2 일 동안 많은 연구를 한 후에 모든 데이터 소스를 초기화하는 솔루션을 발견했습니다. hibernate의 SchemaExport.class를 사용하여 로컬 H2 데이터베이스를 생성하고 초기화하는 메소드를 만들었습니다. 테스트를 위해 로컬 DB 만 필요하기 때문에 @ 이전의 오이 메서드에서 각 DatabaseEnvirement에 대한 메서드를 호출합니다.

    지난 2 일 동안 많은 연구를 한 후에 모든 데이터 소스를 초기화하는 솔루션을 발견했습니다. hibernate의 SchemaExport.class를 사용하여 로컬 H2 데이터베이스를 생성하고 초기화하는 메소드를 만들었습니다. 테스트를 위해 로컬 DB 만 필요하기 때문에 @ 이전의 오이 메서드에서 각 DatabaseEnvirement에 대한 메서드를 호출합니다.

    public void createDatabase(DatabaseEnvironment environment)
    throws Exception
    {
        // load hibernate configuration from hibernate.cfg.xml in classpath
        Configuration configuration = new Configuration().configure();
        MetadataSources metadata =
        new MetadataSources(new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build());
    
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
    
        for (BeanDefinition def : scanner.findCandidateComponents(MarkEntity.class.getPackage().getName()))
        {
            metadata.addAnnotatedClass(Class.forName(def.getBeanClassName()));
        }
    
        Connection connection = DriverManager.getConnection("jdbc:h2:mem:test-" + environment.name().toLowerCase(), "sa", "");
    
        SchemaExport export = new SchemaExport((MetadataImplementor) metadata.buildMetadata(), connection);
        export.create(true, true);
    }
    
    
    @Before
    public void beforeTest()
        throws Exception
    {
        // initialise databases
        for (DatabaseEnvironment env : DatabaseEnvironment.values())
        {
            createDatabase(env);
        }
    }
    

    이것이 내 hibernate.cfg.xml의 모습이다.

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
        <session-factory>
    
            <property name="dialect">org.hibernate.dialect.H2Dialect</property>
    
            <property name="show_sql">true</property>
    
            <property name="hbm2ddl.auto">create-drop</property>
    
        </session-factory>
    </hibernate-configuration>
    
  2. from https://stackoverflow.com/questions/47138617/initialize-multiple-databases-in-spring by cc-by-sa and MIT license