I’m trying to dynamic route my transactions to the READ_WRITE or READ_ONLY datasources.
But in my class TransactionRoutingDataSource extends AbstractRoutingDataSource
when i am trying to get the value of TransactionSynchronizationManager.isCurrentTransactionReadOnly()
it always returns false.
I already try to set a context using a custom annotation, but the context is setting after when i want to use it, to route my transactions, can anyone help me?
Just getting a infomation in the TransactionRoutingDataSource will solve my problem.
I tested with default values (DataSourceType.READ_WRITE & DataSourceType.READ_ONLY) and it works, the transaction is routed to the correct Database
TransactionRoutingDataSource
package com.example.wsappsiav.MultipleDatabase.Configuration.Teste;
import com.example.wsappsiav.MultipleDatabase.Properties.DatabaseContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class TransactionRoutingDataSource extends AbstractRoutingDataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(TransactionRoutingDataSource.class);
@Override
protected Object determineCurrentLookupKey() {
boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
LOGGER.info("Routed to : " + DatabaseContextHolder.getEnvironment());
LOGGER.info("isReadOnly : " + isReadOnly);
return DatabaseContextHolder.getEnvironment();
}
}
ReadReplicaAspect
package com.example.wsappsiav.MultipleDatabase;
import com.example.wsappsiav.MultipleDatabase.Configuration.Teste.DataSourceType;
import com.example.wsappsiav.MultipleDatabase.Properties.DatabaseContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Aspect
@Component
public class ReadReplicaAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(ReadReplicaAspect.class);
@Around("@annotation(com.example.wsappsiav.MultipleDatabase.annotations.UseReadReplica)")
public Object routeToReadReplica(ProceedingJoinPoint joinPoint) throws Throwable {
LOGGER.info("Setting database context to " + DataSourceType.READ_ONLY);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(true);
LOGGER.info("Transaction Mananger: " + TransactionSynchronizationManager.isCurrentTransactionReadOnly());
DatabaseContextHolder.set(DataSourceType.READ_ONLY);
return joinPoint.proceed();
}
}
ClienteService
@Service
public class ClienteService {
@Autowired
private ClienteRepository clienteRepository;
@Transactional(readOnly = true, propagation = Propagation.MANDATORY)
@UseReadReplica
public List<Cliente> listarTodosClientes() {
return clienteRepository.findAll();}
ReplicaDataSource
package com.example.wsappsiav.MultipleDatabase.Configuration.replica;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface ReplicaDataSource {
}
LOG’S
2024-05-14T10:13:08.676-03:00 INFO 15568 --- [ws-app-siav] [nio-8080-exec-1] c.e.w.M.C.T.TransactionRoutingDataSource : Routed to : null
2024-05-14T10:13:08.676-03:00 INFO 15568 --- [ws-app-siav] [nio-8080-exec-1] c.e.w.M.C.T.TransactionRoutingDataSource : isReadOnly : false
2024-05-14T10:13:08.868-03:00 INFO 15568 --- [ws-app-siav] [nio-8080-exec-1] c.e.w.M.ReadReplicaAspect : Setting database context to READ_ONLY
2024-05-14T10:13:08.868-03:00 INFO 15568 --- [ws-app-siav] [nio-8080-exec-1] c.e.w.M.ReadReplicaAspect : Transaction Mananger: true
2024-05-14T10:13:08.947-03:00 DEBUG 15568 --- [ws-app-siav] [nio-8080-exec-1] org.hibernate.SQL : select c1_0.id,c1_0.cliente_nome,c1_0.cpf_cnpj,c1_0.email,c1_0.endereco,c1_0.telefone from bd_siav.cliente c1_0
Hibernate: select c1_0.id,c1_0.cliente_nome,c1_0.cpf_cnpj,c1_0.email,c1_0.endereco,c1_0.telefone from bd_siav.cliente c1_0
application.properties
spring.aop.proxy-target-class=true
spring.jpa.properties.org.hibernate.flushMode = MANUAL
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
spring.jpa.hibernate.ddl-auto=none
spring.sql.init.mode=always
spring.sql.init.continue-on-error=true
Eric Borges is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.