【发布时间】: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