我有与PostgreSQL数据库一起工作的Sping Boot 应用程序。
我只有一个数据源,用于Spring Data JPA操作和Liquibase迁移(我猜)。
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://*************/*****
username:*******
password:*******
type: com.zaxxer.hikari.HikariDataSource
connection-test-query: SELECT 1;
idle-timeout: 30000
maximum-pool-size: 100
minimum-idle: 7
jpa:
hibernate:
ddl-auto: validate
database-platform: org.hibernate.dialect.PostgreSQLDialect
show-sql: false
properties:
hibernate:
default_schema: public
format_sql: true
enable_lazy_load_no_trans: true
generate_statistics: false
jdbc.batch_size: 100
order_inserts: true
order_updates: true
jdbc.batch_versioned_data: true
query.fail_on_pagination_over_collection_fetch: true
liquibase:
liquibase-schema: public
default-schema: public
change-log: classpath:db/changelog/db.changelog-master.xml
我还有一个Sping Boot 配置类,它指定了我希望在应用程序中使用哪一个事务管理器。
@Configuration
public class TransactionManagerConfig {
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(sessionFactory);
return transactionManager;
}
}
当使用我的数据库时,我必须用不同的方式与我的数据进行通信。第一种是使用带有@Transactional注解的服务方法。例如,为了简单阅读,我使用下面的方法:
@Transactional(readOnly = true, isolation = Isolation.READ_COMMITTED)
public List<Dto> fetchAll() {...
另一种方式稍微复杂一点,但仍然很常见。例如,对于更新,我手动与事务交互:
@Service
public class EntityService {
@Autowired
private DocumentRepository documentRepository;
@Autowired
private PlatformTransactionManager transactionManager;
public Long update(Long id, Entity entity) {
DefaultTransactionDefinition transForCursor = new DefaultTransactionDefinition();
transForCursor.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
transForCursor.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus cursorTransactionStatus = transactionManager.getTransaction(transForCursor);
try {
//...
//here I am interactiong with S3 File storage
//...
savedEntity = entityRepository.save(entity);
} catch (Exception e) {
//...
//if I catch any exception I should delete files from S3 File storage
//which I just uploaded and only then I should rollback database transaction
//...
if (!(e instanceof RuntimeException)) {
transactionManager.rollback(cursorTransactionStatus);
}
throw e;
}
try {
transactionManager.commit(cursorTransactionStatus);
} catch (Exception e) {
//...
//if any exception happens when I was trying to commit I still should delete files
//...
throw new TransactionException();
}
return savedEntity.getId();
}
}
问题是,有时候在调用read或update方法时会出现以下异常:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
但是有时候它运行的很好,没有任何错误,最有趣的是,上次我遇到这个问题的时候,每十次调用我的read方法,就会出现这个异常。
有没有人知道为什么会发生这种情况以及如何解决它?非常感谢您的时间和您的答案!
我试图通过在read方法中添加@Transactional注解来修复它。我还在定义事务管理器的配置类中添加了@Primay注解。但不幸的是,它对我没有帮助。我试图在这里找到相同的问题,但我没有满足相同的条件。
1条答案
按热度按时间ohfgkhjo1#
那个模式:
肯定是不正确的,经验法则是:你必须在你开始的地方完成(提交或回滚)事务。2但是在你的情况下,这是不正确的,所以你遇到了资源泄漏和其他相关的后果。
如果需要在事务回滚时清除某些外部资源,可以使用以下选项:
1.春田道:
1.冬眠道:
1.另一个冬眠者道: