【SQLException】 QueryRunner

本文详细解析了在使用QueryRunner进行数据库操作时遇到的无DataSource或Connection传递的问题,并提供了有效的解决方案,通过调整代码结构,确保了数据源的正确配置。

报错:

Caused by: java.lang.RuntimeException: java.sql.SQLException: QueryRunner requires a DataSource to be invoked in this way, or a Connection should be passed in
	at dao.CustomerDao.findAll(CustomerDao.java:129)
	at service.CustomerService.findAll(CustomerService.java:27)
	at servlet.CustomerServlet.findAll(CustomerServlet.java:61)
	... 18 more

根据https://blog.youkuaiyun.com/u010782846/article/details/51327186
可知

 Number number=(Number) qr.query(sql,new ScalarHandler<>());

改成

Number number=(Number) qr.query(con, sql,new ScalarHandler<>());

ok

<think> 嗯,用户现在想了解QueryRunner的带参构造器相关信息。结合之前的对话历史,用户已经接触过QueryRunner的基本用法和BeanHandler的使用场景[^1][^2][^3],现在更关注构造器层面的细节。 用户可能正在解决连接管理问题,因为QueryRunner有两种构造器差异正是围绕是否由调用方管理连接设计的。引用[5]提到的SQLException也暗示用户在连接管理上可能踩过坑[^5],这进一步说明用户需要明确构造器的选择逻辑。 从技术角度看需要分两层解释: 首先是基础构造器&mdash;&mdash;无参版本每次执行SQL都需显式传递Connection对象,适合需要精细控制事务的场景[^2]。比如: ```java QueryRunner runner = new QueryRunner(); runner.query(conn, "SELECT...", handler); // 需手动关闭conn ``` 这种模式在Spring事务管理中很常见,但容易忘记关闭连接。 其次是带DataSource参数的构造器&mdash;&mdash;这是更推荐的生产环境用法,内部自动管理连接池: ```java // 创建时注入连接池 QueryRunner runner = new QueryRunner(dataSource); runner.query("SELECT...", handler); // 无需传递conn ``` 这种方案能避免连接泄漏,尤其配合HikariCP等连接池时[系统知识]。 用户可能没意识到的是:带参构造器还能避免线程安全问题。因为每个QueryRunner实例会从DataSource获取独立连接,多线程环境下更安全[^2]。这一点在文档里不太显眼但很重要。 最后要提醒的是,两种构造器在异常处理上有差异。带DataSource的版本会自动回滚未提交事务并归还连接,而无参版本需要开发者手动处理回滚[^2]。这个细节在引用[5]的报错场景中可能被忽略了[^5]。 要不要补充事务边界控制的示例代码呢?不过用户当前焦点在构造器,先保持回答精简为好。后续如果用户问到事务再展开。 </think> ### QueryRunner 带参构造器详解 #### **1. 核心构造器** QueryRunner 有两种带参构造器,核心区别在于**连接管理方式**: | 构造器签名 | 连接管理方式 | 适用场景 | |---------------------------------------------|-----------------------|----------------------------| | `QueryRunner(DataSource ds)` | **自动管理连接池** | 生产环境首选 | | `QueryRunner(DataSource ds, StatementProcessor stmt)` | 自动管理+自定义语句处理 | 需SQL拦截/改写等高级场景[^2] | ```java // 示例:使用DataSource初始化(推荐) DataSource ds = new HikariDataSource(); // 连接池实例 QueryRunner runner = new QueryRunner(ds); // 注入DataSource // 执行查询(无需手动关闭连接) List<User> users = runner.query("SELECT * FROM users", new BeanListHandler<>(User.class)); ``` #### **2. 关键特性** - **连接自动回收** 使用 `DataSource` 参数构造时,QueryRunner 会自动: ```mermaid graph LR A[调用query/update方法] --> B[从DataSource获取连接] B --> C[执行SQL操作] C --> D{是否异常?} D -->|否| E[归还连接到连接池] D -->|是| F[回滚事务并关闭连接] ``` - **线程安全保证** 每个线程通过 `getConnection()` 获取独立连接,避免并发冲突[^2] - **资源泄漏防护** 即使发生异常,连接仍会被正确关闭(通过 `finally` 块保证) #### **3. 对比无参构造器** ```java // 无参构造器示例(需手动管理连接) QueryRunner runner = new QueryRunner(); Connection conn = ds.getConnection(); try { runner.query(conn, "SELECT...", handler); // 需显式传递连接 } finally { DbUtils.closeQuietly(conn); // 必须手动关闭 } ``` **核心差异**: | 特性 | 带参构造器 | 无参构造器 | |--------------------|--------------------------|-------------------| | 连接获取 | 自动从DataSource获取 | 需外部传入连接 | | 连接关闭 | 自动归还连接池 | 必须手动关闭 | | 事务边界控制 | 每次操作独立事务 | 可跨多个操作 | | 资源泄漏风险 | ️ 极低 | ⚠️ 需严格保证关闭 | #### **4. 注意事项** 1. **连接池要求** 传入的 `DataSource` 必须是连接池实现(如 HikariCP/Druid) ```java // 错误示例(非连接池会频繁创建物理连接) DataSource badDS = new DriverManagerDataSource(url,user,pwd); QueryRunner runner = new QueryRunner(badDS); // ❌ 性能灾难 ``` 2. **自定义语句处理器** 高级用法示例(如SQL日志记录): ```java StatementProcessor logProcessor = (Connection conn, String sql) -> { System.out.println("[SQL] " + sql); // 打印SQL日志 return conn.prepareStatement(sql); }; QueryRunner runner = new QueryRunner(ds, logProcessor); ``` 3. **事务管理限制** 该构造器**不适合跨多操作的事务**,如需事务控制应使用: ```java Connection conn = ds.getConnection(); conn.setAutoCommit(false); try { runner.update(conn, "UPDATE..."); runner.update(conn, "INSERT..."); conn.commit(); } catch (SQLException e) { conn.rollback(); } finally { DbUtils.closeQuietly(conn); } ``` --- ### 相关问题 1. 使用 `QueryRunner(DataSource ds)` 时,如何确保连接池参数(如 `maxPoolSize`)配置合理? 2. 在分布式事务场景中,`QueryRunner` 如何配合 `XAConnection` 实现两阶段提交?[^4] 3. 当需要为所有执行的SQL自动添加租户ID过滤条件时,应如何扩展 `StatementProcessor`? 4. `BeanHandler` 要求实体类有无参构造器,如果实体类只有全参构造器该如何处理?[^5] 5. 对比 Spring JDBC Template 与 Apache DbUtils 的 `QueryRunner`,二者的性能差异主要体现在哪些方面? [^1]: QueryRunner核心构造器 [^2]: DbUtils连接管理机制 [^4]: 分布式事务处理 [^5]: 实体类构造要求
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值