我的目标是在分页、排序和过滤中实现dao方法。对于分页,我需要首先获取计数,然后设置偏移量和限制,并获取结果(所以只从数据库中获取一个“页面”):
@Slf4j
@Repository
public class UserJdbcRepository {
private final SQLQueryFactory queryFactory;
@Autowired
public UserJdbcRepository(DataSource dataSource) {
Configuration configuration = new Configuration(new OracleTemplates());
configuration.setExceptionTranslator(new SpringExceptionTranslator());
this.queryFactory = new SQLQueryFactory(configuration, dataSource);
}
public Page<User> findAll(BooleanExpression predicate, Pageable pageable) {
QUser u = new QUser("u");
SQLQuery<Tuple> sql = queryFactory
.select(u.userId, // omitted)
.from(u)
.where(predicate);
long count = sql.fetchCount();
List<Tuple> results = sql.fetch();
// Conversion List<Tuple> to List<User> omitted
return new PageImpl<>(users, pageable, count);
}
}fetchCount()被正确执行,但fetch()抛出了NullPointerException:
java.lang.NullPointerException: null
at com.querydsl.sql.AbstractSQLQuery.fetch(AbstractSQLQuery.java:502) ~[querydsl-sql-4.4.0.jar:na]从debug中我发现根本原因在com.querydsl.sql.AbstractSQLQuery:
java.sql.SQLException: Connection is closed如果我创建第二个(与第一个相同)查询sql2,那么它(当然)是有效的:
SQLQuery<Tuple> sql2 = queryFactory
.select(... // same as first one)
long count = sql.fetchCount();
List<Tuple> results = sql2.fetch();我的问题是,在调用fetchCount()之后,连接是否真的应该关闭?或者我有一些错误的配置?
我有SpringBoot 2.4.5;spring-data-commons 2.5.0;Oracle driver ojdbc8 21.1.0.0;QueryDSL 4.4.0
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql</artifactId>
<version>${querydsl.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
<version>${querydsl.version}</version>
<scope>compile</scope>
</dependency>
<plugin>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>${querydsl.version}</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbcDriver>oracle.jdbc.OracleDriver</jdbcDriver>
<jdbcUrl>jdbc:oracle:thin:@//localhost:1521/XE</jdbcUrl>
<jdbcUser>user</jdbcUser>
<jdbcPassword>password</jdbcPassword>
<sourceFolder>${project.basedir}/src/main/java</sourceFolder>
<targetFolder>${project.basedir}/src/main/java</targetFolder>
<packageName>org.project.backend.repository.querydsl</packageName>
<schemaToPackage>true</schemaToPackage>
<schemaPattern>project</schemaPattern>
<tableNamePattern>
// omitted
</tableNamePattern>
</configuration>
<plugin>发布于 2021-04-30 04:11:20
问题是由配置错误引起的。QueryDSL doc包含Spring集成部分,其中提到必须使用SpringConnectionProvider。所以我更改了我的构造函数,现在它可以正常工作了:
@Autowired
public UserJdbcRepository(DataSource dataSource) {
Configuration configuration = new Configuration(new OracleTemplates());
configuration.setExceptionTranslator(new SpringExceptionTranslator());
// wrong: this.queryFactory = new SQLQueryFactory(configuration, dataSource);
Provider<Connection> provider = new SpringConnectionProvider(dataSource);
this.queryFactory = new SQLQueryFactory(configuration, provider);
}我还发现有一个有用的方法fetchResults(),其中包含用于分页的count (因此不需要显式调用fetchCount()):
public Page<User> findAll(BooleanExpression predicate, Pageable pageable) {
QUser u = new QUser("u");
SQLQuery<Tuple> sql = queryFactory
.select(u.userId, // omitted)
.from(u)
.where(predicate);
sql.offset(pageable.getOffset());
sql.limit(pageable.getPageSize());
QueryResults<Tuple> queryResults = sql.fetchResults();
long count = queryResults.getTotal();
List<Tuple> results = queryResults.getResults();
// Conversion List<Tuple> to List<User> omitted
return new PageImpl<>(users, pageable, count);
}https://stackoverflow.com/questions/67323853
复制相似问题