运行springboot2.3.0版本,配置了两个数据源。在尝试将实体保存到数据库时,出现以下异常。同样的代码使用的是单个数据源。我们遵循了此处找到的多个数据源的设置:https://www.baeldung.com/spring-data-jpa-multiple-databases
你知道会发生什么或者为什么找不到交易吗?
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:403)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy190.saveAndFlush(Unknown Source)
at com.xyz.service.KeyHelperService.createKey(KeyHelperService.java:137)
at com.xyz.service.KeyHelperService.lambda$0(KeyHelperService.java:86)
at java.util.Optional.orElseGet(Optional.java:267)
at com.xyz.service.KeyHelperService.createAndRotateKey(KeyHelperService.java:76)
at com.xyz.service.KeyHelperService$$FastClassBySpringCGLIB$$6668f0c7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
keyhelperservice在发生异常的第行的代码段:
@Audited(...)
@PreAuthorize(...)
@Transactional
public EncryptionKeyMetadata createKey() {
...
Entity e = new Entity();
...
EncryptionKeyMetadata key = keyMetadataRepo.saveAndFlush(e);
return key;
}
主数据源配置:
@Configuration
@EnableTransactionManagement
@ConfigurationProperties("spring.datasource")
public class DataSourceConfigWrite extends HikariConfig {
@Autowired
private HikariWriteProperties hikariWriteProperties;
@Autowired
private HibernateConfig hibernateConfig;
@PostConstruct
public void setHikariProps() {
setPoolName(hikariWriteProperties.getPoolName());
setMinimumIdle(hikariWriteProperties.getMinimumIdle());
setMaximumPoolSize(hikariWriteProperties.getMaximumPoolSize());
setIdleTimeout(hikariWriteProperties.getIdleTimeout());
}
@Bean(name = "writeDataSource")
@Primary
public HikariDataSource dataSourceWrite() {
return new HikariDataSource(this);
}
@Bean(name = "entityManagerFactoryWrite")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryWrite(
final @Qualifier("writeDataSource") HikariDataSource dataSourceWrite) {
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setJpaDialect(new HibernateExtendedJpaDialect());
DataSourceReadWriteUtil.setEntityManagerProperties(entityManager, dataSourceWrite, hikariWriteProperties.getPackageNames(), hikariWriteProperties.getType(), hibernateConfig);
return entityManager;
}
@Bean
@Primary
public PlatformTransactionManager transactionManagerWrite(@Qualifier("entityManagerFactoryWrite") EntityManagerFactory entityManagerFactoryWrite) {
return new JpaTransactionManager(entityManagerFactoryWrite);
}
}
数据源配置代码段:
@Configuration
@ConfigurationProperties("spring.datasource")
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryWrite",
transactionManagerRef = "transactionManagerWrite",
basePackages = {"com.xyz.db.repo"}
)
public class CustomDataSourceConfigWrite {
}
application.yml代码段:
spring:
jpa:
hibernate:
ddl-auto: none
properties:
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
hibernate.jdbc.time_zone: UTC
main:
banner-mode: "off"
datasource-read:
driver-class-name: com.mysql.cj.jdbc.Driver
url: 'jdbc:mysql://${db.host:localhost}:${db.port:3336}/xyz_n'
jdbcUrl: 'jdbc:mysql://${db.host:localhost}:${db.port:3336}/xyz_n'
username: xyz_n
password: xyz_n
platform: mysql
hikari:
idle-timeout: 10000
maximum-pool-size: 10
minimum-idle: 5
pool-name: ReadHikariPool
package-Names: com.xyz.db.repo
type: read
datasource:
url: 'jdbc:mysql://${db.host:localhost}:${db.port:3336}/xyz'
jdbcUrl: 'jdbc:mysql://${db.host:localhost}:${db.port:3336}/xyz'
username: xyz
password: xyz
initialSize: 5
minIdle: 5
maxActive: 30
maxIdle: 30
maxWait: 1000000
defaultAutoCommit: false
validationQuery: SELECT 1
testOnBorrow: true
testWhileIdle: true
timeBetweenEvictionRunsMillis: 10000
minEvictableIdleTimeMillis: 30000
jmxEnabled: true
removeAbandonedTimeout: 120
removeAbandoned: true
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 100
minimum-idle: 5
connection-timeout: 30000
max-lifetime: 5000
idle-timeout: 1000
pool-name: WriteHikariPool
package-Names: com.xyz.db.repo
type: write
暂无答案!
目前还没有任何答案,快来回答吧!