I am following this link
https://github.com/kwon37xi/replication-datasource
I have implemented the code But STILL Both my service functions are using the same Database(one which is marked primary)
Service Class
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);
}
}
Then Added two Class(from the link)
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 file
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
Repository
public interface Table1Repo extends JpaRepository<Table1, Integer>{}
Issue is my both service functions are using the primary Database. What am I missing. I only have these class. Rest I have one Controller
Edited I have made by code work by adding this class
@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();
}
}
I'm the writer of the link you refered.
Which data source do you use with Table1Repo?
You have to inject the specific bean "dataSource" to you JDBC call.
I guess
@Primary
"writeDataSource" is injected to your Repository.Try to change
@Primary
to "dataSource" or find a way to inject "dataSource" to your repository.