在JSP中使用多个ResultSet的问题求助
解决JSP中执行两条SQL生成两个数据表的问题
嗨,作为JSP新手遇到这种问题太正常啦!单独跑一条SQL没问题,两条就翻车,大概率是资源管理、事务控制或者代码结构的小问题,我来帮你一步步排查解决~
先看最可能踩的坑和对应的解决方案
1. 资源没正确关闭,导致连接泄漏
单独执行一条时,可能连接没关闭也能蒙混过关,但两条操作时,数据库连接被占满或者语句对象冲突就会报错。一定要在finally块里依次关闭Statement和Connection,顺序别搞反(先关Statement,再关Connection)。
2. 没指定具体数据库就执行SQL
你的连接地址是jdbc:mysql://localhost:3306/,获取连接时必须加上数据库名supr,也就是connectionUrl + dbName,不然数据库不知道要操作哪个库,肯定会失败。
3. 缺少事务控制,一条出错另一条也白搭
如果第一条SQL执行成功,第二条失败,之前的操作可能没回滚,导致数据不一致。最好开启手动提交,两条都成功再commit,出错就rollback。
4. SQL语法或重复创建表的问题
如果表已经存在,直接执行CREATE TABLE会报错,建议用CREATE TABLE IF NOT EXISTS来避免这个问题;另外两条SQL要分别检查语法,有没有漏写分号、字段类型错误等。
给你一份可直接参考的完整代码示例
<%@ page import="java.sql.*" %> <% // 数据库配置 String driverName = "com.mysql.jdbc.Driver"; String connectionUrl = "jdbc:mysql://localhost:3306/"; String dbName = "supr"; String userId = "root"; String password = "secret"; // 声明资源对象,初始化为null Connection conn = null; Statement stmt1 = null; Statement stmt2 = null; try { // 加载数据库驱动 Class.forName(driverName); // 获取连接时务必带上数据库名 conn = DriverManager.getConnection(connectionUrl + dbName, userId, password); // 关闭自动提交,开启手动事务控制 conn.setAutoCommit(false); // 第一条创建表的SQL String createTableSql1 = "CREATE TABLE IF NOT EXISTS user_info (" + "id INT PRIMARY KEY AUTO_INCREMENT," + "username VARCHAR(50) NOT NULL UNIQUE," + "age INT)"; stmt1 = conn.createStatement(); stmt1.executeUpdate(createTableSql1); out.println("第一个数据表创建成功!<br>"); // 第二条创建表的SQL String createTableSql2 = "CREATE TABLE IF NOT EXISTS order_record (" + "order_id INT PRIMARY KEY AUTO_INCREMENT," + "user_id INT," + "order_time DATETIME," + "FOREIGN KEY(user_id) REFERENCES user_info(id))"; stmt2 = conn.createStatement(); stmt2.executeUpdate(createTableSql2); out.println("第二个数据表创建成功!<br>"); // 两条操作都成功,提交事务 conn.commit(); } catch (ClassNotFoundException e) { out.println("数据库驱动加载失败:" + e.getMessage()); e.printStackTrace(); } catch (SQLException e) { // 出错就回滚事务,避免脏数据 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } out.println("数据库操作出错:" + e.getMessage()); e.printStackTrace(); } finally { // 务必关闭所有资源,顺序不能错 try { if (stmt2 != null) stmt2.close(); if (stmt1 != null) stmt1.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } %>
额外的规范建议
其实JSP里最好少写这种脚本代码,把数据库操作放到单独的Java工具类(比如DBUtil)或者DAO类里,JSP只负责展示结果,这样代码更易维护和调试。举个简单的工具类例子:
// DBUtil.java(放到你的项目src目录下,比如com.util包) package com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class DBUtil { // 配置常量写在这儿,不用每次重复写 private static final String DRIVER = "com.mysql.jdbc.Driver"; private static final String DB_URL = "jdbc:mysql://localhost:3306/supr"; private static final String USER = "root"; private static final String PWD = "secret"; // 静态代码块,只加载一次驱动 static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new RuntimeException("数据库驱动加载失败", e); } } // 获取连接的方法 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(DB_URL, USER, PWD); } // 关闭资源的工具方法 public static void closeResources(Connection conn, Statement stmt) { try { if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
然后在JSP里调用这个工具类:
<%@ page import="java.sql.*" %> <%@ page import="com.util.DBUtil" %> <% Connection conn = null; Statement stmt = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 复用同一个Statement执行两条SQL,节省资源 stmt = conn.createStatement(); stmt.executeUpdate("CREATE TABLE IF NOT EXISTS user_info (...)"); stmt.executeUpdate("CREATE TABLE IF NOT EXISTS order_record (...)"); conn.commit(); out.println("两个数据表都成功创建啦!"); } catch (SQLException e) { if (conn != null) { try { conn.rollback(); } catch (SQLException ex) {} } out.println("操作失败:" + e.getMessage()); } finally { DBUtil.closeResources(conn, stmt); } %>
内容的提问来源于stack exchange,提问作者mach413
相关产品推荐
相关产品推荐

