最近,我在Spring Boot应用程序中尝试了一种用于数据库访问的新工具Querydsl,这是我在@Configuration
类中配置上下文的方式:
@Bean
public com.querydsl.sql.Configuration querydslConfiguration() {
SQLTemplates templates = OracleTemplates.builder().build();
com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);
configuration.setExceptionTranslator(new SpringExceptionTranslator());
return configuration;
}
@Bean
public SQLQueryFactory queryFactory(DataSource dataSource) {
Provider<Connection> provider = new SpringConnectionProvider(dataSource);
return new SQLQueryFactory(querydslConfiguration(), provider);
}
我的查询是一个非常简单的选择:
fun detailedEntityByIds(ids: Set<String>): List<DetailedEntity> {
val qDetails = QTContainerDetails.tContainerDetails
return sqlQueryFactory.select(qDetails).from(qDetails)
.where(qDetails.id.`in`(ids))
.fetch().map { mapper.qDslEntToModel(it) }
}
然后我遇到以下异常:
java.lang.IllegalStateException:连接不是事务性的
我很快发现了一个问题:[QueryDSL/Spring]java.lang.IllegalStateException: Connection is not transactional,并提出了使用@Transactional
解决此问题的建议。
为什么Querydsl要求连接是事务性的?我曾经将@Transactional
放在我真正需要的服务层方法上。现在Querydsl强迫我将其放在整个DAO类上,因为看起来每个Querydsl查询都需要它。
答案 0 :(得分:1)
来自Javadoc
/**
* {@code SpringConnectionProvider} is a Provider implementation which provides a transactionally bound connection
*
* <p>Usage example</p>
* <pre>
* {@code
* Provider<Connection> provider = new SpringConnectionProvider(dataSource());
* SQLQueryFactory queryFactory = SQLQueryFactory(configuration, provider);
* }
* </pre>
*/
原因是用于资源管理。您无权访问基础JDBC实现。事务将关闭ResultSet,语句,连接等。如果没有事务,则每个连接将保持打开状态,连接池饱和,数据库资源耗尽等。
如果您要管理自己的资源,则可以编写自己的Provider<Connection>
并传递DataSource
E.G。
private static Provider<Connection> getConnection(DataSource dataSource) {
return () -> org.springframework.jdbc.datasource.DataSourceUtils.getConnection(dataSource);
}