JTA EntityManager 不能使用 getTransaction() - 但只能在控制器中使用
A JTA EntityManager cannot use getTransaction() - but only in controller
我正在尝试使用 Spring Data JPA 存储库来获取和保留实体。当我从例如内部使用此存储库时Quartz 工作,一切正常。当我尝试从 RestController 中使用此存储库时,我收到以下错误消息:"A JTA EntityManager cannot use getTransaction()"。当然,我在谷歌上搜索了一个解决方案,但我的案例似乎与我发现的案例有点不同。有什么想法可能会导致此类错误吗?
使用此存储库的服务示例 class:
@Service
public class ServiceToTablesMappingServiceImpl implements ServiceToTablesMappingService {
@Autowired
private ServiceToTablesMappingRepository repo;
/**
* {@inheritDoc}
*/
@Override
public void createMapping(String serviceName, Set<String> tables) {
for (String table : tables) {
ServiceToTablesMappingEntity entity = new ServiceToTablesMappingEntity();
entity.setServiceName(serviceName);
entity.setTableName(table);
this.repo.save(entity); //this line causes the error
}
}
...
我的回购代码:
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import xxx.ServiceToTablesMappingEntity;
@Repository
public interface ServiceToTablesMappingRepository extends CrudRepository<ServiceToTablesMappingEntity, Long> {
@Transactional
List<ServiceToTablesMappingEntity> findByServiceName(String serviceName);
}
控制器代码:
@RestController
public class InitialLoadController {
...
@Autowired
private ServiceToTablesMappingService regService;
/**
* Triggers the initial load workflow preparation
*
* @param service The service which tries to prepare
* @param request The request which contains a list of tables along with some other information about the subscriber
* @return Return the 200 status code if everything went fine
*/
@PostMapping("/init-prepare")
public ResponseEntity<Void> initPrepare(@RequestBody InitialLoadRequestDto request) {
// create mapping
Set<String> tables = request.getTables();
String service = request.getServiceName();
this.regService.createMapping(service, tables);
...
return ResponseEntity.ok().build();
}
...
下面是我如何配置 entityManager:
@Configuration
@DependsOn("transactionManager")
@ComponentScan({ "xxx", "yyy" })
@EnableJpaRepositories(basePackages = { "xxx",
"yyy" }, entityManagerFactoryRef = "datasupplyEntityManager", transactionManagerRef = "transactionManager", queryLookupStrategy = Key.CREATE_IF_NOT_FOUND)
@EnableConfigurationProperties(DbDatasourceProperties.class)
public class DatasupplyConfig {
...
@Bean(name = "datasupplyEntityManager")
@DependsOn("jpaVendorAdapter")
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter jpaVendorAdapter,
DataSource xaDataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
properties.put("hibernate.temp.use_jdbc_metadata_defaults", this.useJdbcMetadataDefaults);
LocalContainerEntityManagerFactoryBean entityManagerBean = new LocalContainerEntityManagerFactoryBean();
entityManagerBean.setDataSource(xaDataSource);
entityManagerBean.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerBean.setPackagesToScan("xxx",
"yyyy");
entityManagerBean.setJpaPropertyMap(properties);
return entityManagerBean;
}
...
抱歉,我花了一段时间才回答。我发现了问题。问题确实是 https://whosebug.com/users/1126526/manish 建议的:我必须将数据源更改为 jtaDataSource。我不知道,为什么我以前没有看到。
我正在尝试使用 Spring Data JPA 存储库来获取和保留实体。当我从例如内部使用此存储库时Quartz 工作,一切正常。当我尝试从 RestController 中使用此存储库时,我收到以下错误消息:"A JTA EntityManager cannot use getTransaction()"。当然,我在谷歌上搜索了一个解决方案,但我的案例似乎与我发现的案例有点不同。有什么想法可能会导致此类错误吗?
使用此存储库的服务示例 class:
@Service
public class ServiceToTablesMappingServiceImpl implements ServiceToTablesMappingService {
@Autowired
private ServiceToTablesMappingRepository repo;
/**
* {@inheritDoc}
*/
@Override
public void createMapping(String serviceName, Set<String> tables) {
for (String table : tables) {
ServiceToTablesMappingEntity entity = new ServiceToTablesMappingEntity();
entity.setServiceName(serviceName);
entity.setTableName(table);
this.repo.save(entity); //this line causes the error
}
}
...
我的回购代码:
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import xxx.ServiceToTablesMappingEntity;
@Repository
public interface ServiceToTablesMappingRepository extends CrudRepository<ServiceToTablesMappingEntity, Long> {
@Transactional
List<ServiceToTablesMappingEntity> findByServiceName(String serviceName);
}
控制器代码:
@RestController
public class InitialLoadController {
...
@Autowired
private ServiceToTablesMappingService regService;
/**
* Triggers the initial load workflow preparation
*
* @param service The service which tries to prepare
* @param request The request which contains a list of tables along with some other information about the subscriber
* @return Return the 200 status code if everything went fine
*/
@PostMapping("/init-prepare")
public ResponseEntity<Void> initPrepare(@RequestBody InitialLoadRequestDto request) {
// create mapping
Set<String> tables = request.getTables();
String service = request.getServiceName();
this.regService.createMapping(service, tables);
...
return ResponseEntity.ok().build();
}
...
下面是我如何配置 entityManager:
@Configuration
@DependsOn("transactionManager")
@ComponentScan({ "xxx", "yyy" })
@EnableJpaRepositories(basePackages = { "xxx",
"yyy" }, entityManagerFactoryRef = "datasupplyEntityManager", transactionManagerRef = "transactionManager", queryLookupStrategy = Key.CREATE_IF_NOT_FOUND)
@EnableConfigurationProperties(DbDatasourceProperties.class)
public class DatasupplyConfig {
...
@Bean(name = "datasupplyEntityManager")
@DependsOn("jpaVendorAdapter")
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter jpaVendorAdapter,
DataSource xaDataSource) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
properties.put("hibernate.temp.use_jdbc_metadata_defaults", this.useJdbcMetadataDefaults);
LocalContainerEntityManagerFactoryBean entityManagerBean = new LocalContainerEntityManagerFactoryBean();
entityManagerBean.setDataSource(xaDataSource);
entityManagerBean.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerBean.setPackagesToScan("xxx",
"yyyy");
entityManagerBean.setJpaPropertyMap(properties);
return entityManagerBean;
}
...
抱歉,我花了一段时间才回答。我发现了问题。问题确实是 https://whosebug.com/users/1126526/manish 建议的:我必须将数据源更改为 jtaDataSource。我不知道,为什么我以前没有看到。