我尝试在
@Transactional
方法中使用 @Async
来跟踪文件转换过程,如下所示:
@Async
@Transactional
public void convertFile(String documentId){
CustomLog customLog = new CustomLog();
customLog.setStatus("IN_PROGRESS");
mySpringDataRepo.save(customLog);
try{
doConvertFunction(documentId);
}catch(Exception e){
customLog.setStatus("FAIL");
mySpringDataRepo.save(customLog);
return;
}
customLog.setStatus("SUCCESS");
mySpringDataRepo.save(customLog);
}
我正在使用以下技术:
我的EntityManager配置:
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = builder.dataSource(dataSource).packages("com.myapp").persistenceUnit("MyEntityManagerFactory").properties(jpaProperties()).build();
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
protected Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.physical_naming_strategy", CamelCaseToUnderscoresNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
return props;
}
在 Tomcat 9 上运行上述代码时,它工作得很好,但是当尝试在 Websphere 上运行它时,事务不会打开,并且 save 方法根本不会执行!
我做了几次尝试,但没有成功,如下:
1- 使用
@Transactional(propagation = Propagation.REQUIRES_NEW)
2- 将 save 方法提取为新的单独服务方法,如下所示:
@Service
public class MyService {
@Autowired
private MySpringDataRepo mySpringDataRepo;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public CustomLog save(CustomLog customLog) {
mySpringDataRepo.save(customLog);
return customLog;
}
}
更新:
在 Websphere 上工作的唯一解决方案是通过 EntityManagerFactory 创建 EntityManager,如下所示:
@Service
public class CustomLogService{
@Autowired
private EntityManagerFactory entityManagerFactory;
public Long save(CustomLog customLog) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(customLog);
entityManager.flush();
entityManager.getTransaction().commit();
return customLog.getId();
}
public CustomLog find(Long id) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
CustomLog customLog = entityManager.find(CustomLog.class, id);
entityManager.getTransaction().commit();
return customLog;
}
public void update(CustomLog customLog) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.merge(customLog);
entityManager.getTransaction().commit();
}
}
并将我的@Async代码更改为如下:
@Async
public void convertFile(String documentId){
CustomLog customLog = new CustomLog();
customLog.setStatus("IN_PROGRESS");
customLogService.save(customLog);
try{
doConvertFunction(documentId);
}catch(Exception e){
customLog = customLogService.find(customLog.getId());
customLog.setStatus("FAIL");
customLogService.update(customLog);
return;
}
customLog = customLogService.find(customLog.getId());
customLog.setStatus("SUCCESS");
customLogService.update(customLog);
}
我尝试按如下方式注入entityManager,但它不起作用,只有从EntityManagerFactory创建entityManager才有效:
@PersistenceContext(name = "MyEntityManagerFactory")
private EntityManager entityManager;
此解决方案中是否有任何缺点/需要考虑的事项,因为我将大量使用此方法并且每次调用它时都会返回一个新的 EntityManager 实例?
尝试这个配置代码:
@Configuration
@EnableJpaRepositories(basePackages = { "com.myapp.dao" }, transactionManagerRef = "websphereTxManager")
@EnableTransactionManagement
public class WebSphereDBConfiguration {
@Resource(lookup = "jdbc/sample", name = "java:comp/env/jdbc/sample")
private DataSource dataSource;
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setPackagesToScan("com.myapp.entity");
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties());
return entityManagerFactoryBean;
}
@Bean
public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return entityManagerFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager websphereTxManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
protected Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.physical_naming_strategy", CamelCaseToUnderscoresNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
return props;
}
}