设置上下文 |获取 TransactionSynconizationMananger.isCurrentTransactionReadOnly() 的值

问题描述 投票:0回答:1

我正在尝试将我的事务动态路由到 READ_WRITE 或 READ_ONLY 数据源。

但是在我的类中 TransactionRoutingDataSource 扩展了 AbstractRoutingDataSource

当我尝试获取 TransactionSynchronizationManager.isCurrentTransactionReadOnly() 的值时

它总是返回 false。
我已经尝试使用自定义注释设置上下文,但是上下文是在我想使用它之后设置的,以路由我的事务,任何人都可以帮助我吗?

只需在 TransactionRoutingDataSource 中获取信息即可解决我的问题。

我使用默认值(DataSourceType.READ_WRITE 和 DataSourceType.READ_ONLY)进行了测试,它有效,事务被路由到正确的数据库

交易路由数据源

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();
    }
}

读取ReplicaAspect

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();
    }
}

客户服务

@Service
public class ClienteService {
    @Autowired
    private ClienteRepository clienteRepository;
    @Transactional(readOnly = true, propagation = Propagation.MANDATORY)
    @UseReadReplica
    public List<Cliente> listarTodosClientes() {
        return clienteRepository.findAll();}

副本数据源

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 {
}

日志

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

应用程序属性

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
java spring hibernate transactions dynamic-routing
1个回答
0
投票

解决了。 我删除了TransactionRoutingDataSource的配置,并添加

LazyConnectionDataSourceProxy lazyDateSource = new LazyConnectionDataSourceProxy(dataSource);
lazyDateSource.setReadOnlyDataSource(dataSourceReader);

我查看这个问题

© www.soinside.com 2019 - 2024. All rights reserved.