Spring boot读写分割/主站 - 从站/多个数据库

时间:2017-04-06 06:41:07

标签: spring-boot spring-data-jpa

我正在关注此链接

https://github.com/kwon37xi/replication-datasource

我已经实现了代码但是STILL我的服务函数都使用相同的数据库(一个标记为主要的数据库)

服务类

public class TableService{

    @Autowired
    private Table1Repo t1Repo;
    @Transactional(readOnly = false)
    public void saveTable1(Table1 t,int a, Table1 t2){
            try{
                t1Repo.save(t2);
            }
            catch(Exception e){
                System.out.println("Inside");
            }

    }

    @Transactional(readOnly = true)
    public Table1 getTable(int id){
        return t1Repo.findOne(id);
    }


}

然后添加了两个Class(来自链接)

ReplicationRoutingDataSource

public class ReplicationRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceType = TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? "read" : "write";
        return dataSourceType;
    }
}

WithRoutingDataSourceConfig

@Configuration
public class WithRoutingDataSourceConfig {

    /*@Bean(destroyMethod = "shutdown")*/
    @Bean
    @Primary
    @ConfigurationProperties(prefix="datasource.primary")
    public DataSource writeDataSource() {
       /* EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
                .setName("routingWriteDb")
                .setType(EmbeddedDatabaseType.H2)
                .setScriptEncoding("UTF-8")
                .addScript("classpath:/writedb.sql");
        return builder.build();*/
        return DataSourceBuilder.create().build();
    }

/*    @Bean(destroyMethod = "shutdown")*/
    @Bean
    @ConfigurationProperties(prefix="datasource.secondary")
    public DataSource readDataSource() {
        /*EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
                .setName("routingReadDb")
                .setType(EmbeddedDatabaseType.H2)
                .setScriptEncoding("UTF-8")
                .addScript("classpath:/readdb.sql");
        return builder.build();*/
        return DataSourceBuilder.create().build();
    }

    /**
     * {@link org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource}는
     * {@link org.springframework.beans.factory.InitializingBean}을 구현하므로,
     * 명시적으로 afterPropertiesSet()메소드를 호출하거나
     * 별도 @Bean으로 만들어 Spring Life Cycle을 타도록 해야 한다.
     */
    @Bean
    public DataSource routingDataSource(@Qualifier("writeDataSource") DataSource writeDataSource, @Qualifier("readDataSource") DataSource readDataSource) {
        ReplicationRoutingDataSource routingDataSource = new ReplicationRoutingDataSource();

        Map<Object, Object> dataSourceMap = new HashMap<Object, Object>();
        dataSourceMap.put("write", writeDataSource);
        dataSourceMap.put("read", readDataSource);
        routingDataSource.setTargetDataSources(dataSourceMap);
        routingDataSource.setDefaultTargetDataSource(writeDataSource);

        return routingDataSource;
    }

    /**
     * {@link org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy}로 감싸서
     * 트랜잭션 동기화가 이루어진 뒤에 실제 커넥션을 확보하도록 해준다.
     *
     * @param routingDataSource
     * @return
     */
    @Bean
    public DataSource dataSource(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new LazyConnectionDataSourceProxy(routingDataSource);
    }
}

application.prop文件

server.port=8089

spring.jpa.show-sql = true
spring.jpa.properties.hibernate.show_sql=true

# Primary DataSource configuration
datasource.primary.url=jdbc:mysql://127.0.0.1:3306/jpa
datasource.primary.username=root
datasource.primary.password=root
# Any of the other Spring supported properties below...

# Secondary DataSource configuration
datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/jpa2
datasource.secondary.username=root
datasource.secondary.password=root

存储库

public interface Table1Repo extends JpaRepository<Table1, Integer>{}

问题是我的两个服务功能都在使用主数据库。我错过了什么我只有这些课。休息我有一个控制器

被修改 我通过代码工作添加了这个类

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="com.example")
public class ReplicationDataSourceApplicationConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
        emfb.setDataSource(dataSource);
        emfb.setPackagesToScan("com.example");        
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        emfb.setJpaVendorAdapter(jpaVendorAdapter);

        return emfb;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslationPostProcessor() {
        return new PersistenceExceptionTranslationPostProcessor();
    }
}

2 个答案:

答案 0 :(得分:0)

我是你提到的链接的作者。

您使用Table1Repo的哪个数据源?

你必须注入特定的bean&#34; dataSource&#34;给你JDBC调用。

我想@Primary&#34; writeDataSource&#34;被注入您的存储库。

尝试将@Primary更改为&#34; dataSource&#34;或找到一种方法来注入&#34; dataSource&#34;到您的存储库。

答案 1 :(得分:0)

您也可以通过以下方式尝试:

Spring Boot 2 with Multiple DataSource for Postgres Data Replication

这是github中的源代码:

spring-boot-multi-data-source

以下链接说明,如何拥有多个数据源

DB1(写):

kendoDropDownList.bind("filtering", function(e) {
    // ignore space
    var filterValue = e.sender._prev;
    if(filterValue.trim)filterValue = filterValue.trim();

    var newFilter = {
        logic: "or",
        filters: [
            { field: "FieldA", operator: "contains", value: filterValue },
            { field: "FieldB", operator: "contains", value: filterValue },
            { field: "FieldC", operator: "contains", value: filterValue }
       ]
    };
    this.dataSource.filter(newFilter);

    // important: stop default filter
    e.preventDefault();
});

DB2(读取):

@Configuration
@ConfigurationProperties("spring.datasource-write")
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryWrite",
        transactionManagerRef = "transactionManagerWrite",
        basePackages = {"com.ehsaniara.multidatasource.repository.writeRepository"}
)
public class DataSourceConfigWrite extends HikariConfig {

    public final static String PERSISTENCE_UNIT_NAME = "write";

    @Bean
    public HikariDataSource dataSourceWrite() {
        return new HikariDataSource(this);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryWrite(
            final HikariDataSource dataSourceWrite) {

        return new LocalContainerEntityManagerFactoryBean() {{
            setDataSource(dataSourceWrite);
            setPersistenceProviderClass(HibernatePersistenceProvider.class);
            setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
            setPackagesToScan(MODEL_PACKAGE);
            setJpaProperties(JPA_PROPERTIES);
        }};
    }

    @Bean
    public PlatformTransactionManager transactionManagerWrite(EntityManagerFactory entityManagerFactoryWrite) {
        return new JpaTransactionManager(entityManagerFactoryWrite);
    }
}
相关问题