【问题标题】:Spring Ignores @Transactional is not workingSpring忽略@Transactional 不起作用
【发布时间】:2019-11-28 07:43:24
【问题描述】:

似乎 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 并在类中自动装配它会正常工作

【问题讨论】:

  • 你能不能扩展一下@Transactional is not working。这种“不工作”是如何表现出来的?

标签: transactions spring-data-jpa


【解决方案1】:

在从同一类的另一个方法 m1() 调用的方法 m2() 上使用了 @Transaction 注释。从外部调用 m1() 的位置。

由于没有从外部调用 m2(),所以通过了 spring 代理。

【讨论】:

    猜你喜欢
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多