春天忽略@Transactional无法正常工作

时间:2019-07-19 10:18:30

标签: transactions spring-data-jpa

好像spring忽略了服务类上的@Transactional注释

如果我们手动创建tx bean可以正常工作

@EnableTransactionManagement
@org.springframework.context.annotation.Configuration
@EnableJpaRepositories(basePackages = { DatabaseConstants.SPRING_DATA_REPO_BASE_PACKAGE }, entityManagerFactoryRef = DatabaseConstants.SPRING_DATA_ENTITY_MANAGER_FACTORY)
public class DatabaseConfig {
    private static final Logger LOG = LoggerFactory.getLogger(DatabaseConfig.class);

    @Bean
    public DataSource dataSource(Configuration dataBaseConfig) throws Exception {
        AbstractRoutingDataSource dataSource = new ShardSourceRouter();
        Map<Object, Object> targetDataSources = new HashMap<>();
        for (int i = 1; i <= CCMConfigUtil.getTotalShards(); i++) {
            targetDataSources.put(ShardDatabase.getShardDatabase(i), createDataSource(i, dataBaseConfig));
        }
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(targetDataSources.get(ShardDatabase.SHARD_ONE));
        return dataSource;
    }

    private DataSource createDataSource(int shardNum, Configuration dataBaseConfig) throws Exception {
        JSONObject shardsConfig = new JSONObject(dataBaseConfig.getString(DatabaseConstants.SHARDS_CONFIG));
        JSONObject shard = shardsConfig.getJSONObject(String.valueOf(shardNum));
        DataSourceFactory dataSourceFactory = (DataSourceFactory) dataSourceFactoryLocatorBean().getObject();
        FMSDataSource fmsDataSource = dataSourceFactory.getFMSDataSource(shard
                .getString(DatabaseConstants.DATASOURCE_POOL));
        return fmsDataSource.createDataSource(shard.getJSONObject(DatabaseConstants.PROPERTIES), dataBaseConfig);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean fmsEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = null;
        try {
            Configuration dataBaseConfig = CCMConfigUtil.getDataBaseConfig(System
                    .getProperty(DatabaseConstants.APPLICATION_NAME));
            em = new LocalContainerEntityManagerFactoryBean();
            em.setDataSource(dataSource(dataBaseConfig));
            em.setPackagesToScan(new String[] { DatabaseConstants.SPRING_DATA_ENTITIES_BASE_PACKAGE });
            em.setPersistenceUnitName(DatabaseConstants.PERSISTENCE_UNIT_NAME);
            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            em.setJpaVendorAdapter(vendorAdapter);
            em.setJpaPropertyMap(getJPAProperties(new JSONObject(dataBaseConfig
                    .getString(DatabaseConstants.JPA_PROPERTIES))));
            em.afterPropertiesSet();
            LOG.info("Initialized EntityManagerFactory for PersistenceUnitName {}",
                    DatabaseConstants.PERSISTENCE_UNIT_NAME);
        } catch (final Exception e) {
            LOG.error("Exception while initialize the EntityManagerFactory {}", e);
            throw new RuntimeException("Failed to initialize the EntityManagerFactory", e);
        }
        return em;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        LocalContainerEntityManagerFactoryBean entityManagerFactory = fmsEntityManagerFactory();
        transactionManager.setEntityManagerFactory(entityManagerFactory.getObject());
        transactionManager.setDataSource(entityManagerFactory.getDataSource());
        return transactionManager;
    }

}

@Service
public class FulfillmentRequestManager {

    @Autowired
    private RequestFulfillmentService requestFulfillmentService;

    @Transactional("transactionManager")
    public Long createFulfillmentRequest(String buId, String martId, FulfillmentRequest fulfillmentRequest)
            throws Exception {

        requestFulfillmentService.save(fulfillmentRequestDO, shard);

    }
}

@Service
public class RequestFulfillmentService {

    @Autowired
    private FulfillmentRequestRepository fulfillmentRequestRepository;

    public FulfillmentRequestDO save(FulfillmentRequestDO fulfillmentRequestDO, long shard) {
        FulfillmentRequestDO fulfillmentRequestDOSaved = null;
        Stopwatch stopwatch = Stopwatch.createStarted();
        ShardContext.setCurrentShard(ShardDatabase.getShardDatabase(shard));
        fulfillmentRequestDOSaved = fulfillmentRequestRepository.save(fulfillmentRequestDO);
        LOGGER.info(SplunkLog.getDBLatency(className, "save", DBAction.FetchLatency.name(),
                stopwatch.elapsed(TimeUnit.MILLISECONDS)));
        ShardContext.clear();
        return fulfillmentRequestDOSaved;
    }
}

@Repository
public interface FulfillmentRequestRepository extends JpaRepository<FulfillmentRequestDO, Long> {

}

我在使用@Transactional的类的包中遇到了一些问题。

是否需要添加任何特定的配置来识别只能使用事务注释的类。

或者我定义数据库配置的方式有任何问题。

如果我们手动创建tx bean并在其类中自动连线,则其工作正常

1 个答案:

答案 0 :(得分:0)

在方法m2()上使用@Transaction批注,该方法是从同一类的另一个方法m1()调用的。从外部调用m1()的地方。

由于未从外部spring代理中调用m2(),因此被传递。