首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Querydsl fetchCount() & fetch() Querydsl NullPointerException,连接已关闭

Querydsl fetchCount() & fetch() Querydsl NullPointerException,连接已关闭
EN

Stack Overflow用户
提问于 2021-04-30 03:23:21
回答 1查看 245关注 0票数 0

我的目标是在分页、排序和过滤中实现dao方法。对于分页,我需要首先获取计数,然后设置偏移量和限制,并获取结果(所以只从数据库中获取一个“页面”):

代码语言:javascript
复制
@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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
java.sql.SQLException: Connection is closed

如果我创建第二个(与第一个相同)查询sql2,那么它(当然)是有效的:

代码语言:javascript
复制
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

代码语言:javascript
复制
    <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>
EN

回答 1

Stack Overflow用户

发布于 2021-04-30 04:11:20

问题是由配置错误引起的。QueryDSL doc包含Spring集成部分,其中提到必须使用SpringConnectionProvider。所以我更改了我的构造函数,现在它可以正常工作了:

代码语言:javascript
复制
@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()):

代码语言:javascript
复制
    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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67323853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档