为什么Querydsl总是要求连接是事务性的?

时间:2019-06-24 11:15:38

标签: spring spring-transactions querydsl

最近,我在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查询都需要它。

1 个答案:

答案 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);
}