关于JDBC

        之前接手一个已完成的批量项目,发现其代码写的一塌糊涂,真是醉了,使用了JDBC技术,虽然JDBC比较老旧了,现在也不常用,但是还是记录一下。

        跑了一下程序,报错、、、看了一眼控制台日志,常见的JDBC连接池满了,原因一定是使用了链接但不释放导致的。常见的解决办法有两种,第一,扩大链接池数量,治标不治本;第二,检查程序,使用完的链接要关闭。当即快速检查了程序,发现多处调用JDBC开启链接,但最后都没关闭,并且由于批量程序数据量大,有部分循环调用的情况,导致直接超出连接数量。于是在所有调用完之后都加了close代码。

        再次测试程序,链接数不报错,但是报了超出打开游标的最大数。分析原因,由于部分方法调用JDBC,取到结果集,在结果集内再次循环调用JDBC链接,数据量过多导致;但是如果将游标和结果集resultset关闭,那代码内的循环也将不可使用。时间紧也来不及重构别人的代码,读懂都得耗费时间,于是决定写公共工具类来快速解决。

        写代码思路,第一,工具类单独调取JDBC,原代码只调工具类,工具类使用一次就立即关闭链接、游标和结果集;但是查询类型的需要使用结果集,不可关闭,所以第二查询类型单独写方法并在结束时调用close。代码如下:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SQLHelper {
	private Connection con = null;
	
	private Statement stmt = null;
	
	private PreparedStatement pst = null;
	
	private ResultSet rs = null;
	
	/**
     * 执行 SQL 语句,返回结果为结果集
     * 主要用于执行查询语句
     * @param sql SQL 语句
     * @param cmdParams SQL的参数
     */
	public ResultSet queryHelper(String sql,Object... cmdParams){
		con=JDBCUtil.getDBConnect();
		try {
			pst = con.prepareStatement(sql);
			int i = 1;
	        for (Object item : cmdParams)
	        {
	        	pst.setObject(i, item);
	            i++;
	        }
	        rs = pst.executeQuery();
			return rs;
		} catch (SQLException e) {
			e.printStackTrace();
			try {
				con.rollback();
				con.setAutoCommit(true);
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			return null;
		}
	}
	public void closeAll(){
		JDBCUtil.clearResource(con,stmt,pst,rs);
	}

    /**
     * 执行 SQL 语句,返回结果为整型
     * 主要用于执行非查询语句
     * @param sql SQL 语句
     * @return 非负数:正常执行; -1:执行错误; -2:连接错误
     */
	public int updateHelper(String sql,Object... cmdParams){
		con=JDBCUtil.getDBConnect();
		try {
			pst = con.prepareStatement(sql);
			int i = 1;
	            for (Object item : cmdParams)
	            {
	        	pst.setObject(i, item);
	                i++;
	            }
	            int k;
	            k = pst.executeUpdate();
	            con.commit();
			return k;
		} catch (SQLException e) {
			e.printStackTrace();
			try {
				con.rollback();
				con.setAutoCommit(true);
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			return 0;
		}finally{         
			JDBCUtil.clearResource(con,stmt,pst,rs);
                } 
	    }
}

        具体说明注释里也写的很清楚,就不多说。看下代码调用:

SQLHelper sqh = new SQLHelper();
String sql = "select XXX from XXXXXXXXXXX where XXXXXXXXXXXXXXXXXXXX>0";
ResultSet rst = sqh.queryHelper(sql);

        这种查询类型的,拿到结果集使用完毕后,调用上面工具类中closeAll()方法即刻。

        时间紧,就随便写这些,之后再进行总结和扩展吧。

### 不同数据库与JDBC驱动程序关系 不同数据库与JDBC驱动程序是相互依赖的关系。JDBC并不能直接访问数据库,必须依赖于数据库厂商提供的JDBC驱动程序,不同的数据库厂商会根据JDBC定义的标准接口,开发出适合自己数据库特点的驱动程序,以实现Java程序与该数据库的连接和交互。例如MySQL有自己的JDBC驱动程序`com.mysql.jdbc.Driver`,Oracle也有对应的JDBC驱动程序,这些驱动程序负责处理Java程序与具体数据库之间的通信,满足特定的通信数据格式要求,该数据格式由数据库设备提供商规定 [^1][^2]。 ### Java通过JDBC访问不同数据库时API接口情况 Java通过JDBC访问不同数据库时,使用的是统一的API接口。JDBC定义了一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库的特点去实现这些接口。这样做的目的是希望用相同的方式访问不同的数据库,让具体的数据库操作与数据库厂商实现无关,从而可以在不同数据库之间轻易地进行切换。例如不管是访问MySQL、Oracle还是其他关系型数据库,Java程序都可以使用`DriverManager`类来加载驱动和创建连接,使用`Statement`、`PreparedStatement`等接口来执行SQL语句,使用`ResultSet`类来处理查询结果等 [^3]。 ### Connection类的作用 `Connection`接口在编程时,其对象用于创建`Statement`对象。`Connection`代表Java程序与数据库之间的连接,它是Java程序与数据库进行交互的基础,只有建立了有效的`Connection`对象,才能够进一步创建`Statement`对象,进而向数据库发送SQL语句并处理从数据库返回的结果。例如以下代码展示了如何使用`Connection`对象创建`Statement`对象: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.sql.SQLException; public class ConnectionExample { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/testdb"; String user = "root"; String password = "password"; try { // 建立连接 Connection connection = DriverManager.getConnection(url, user, password); // 使用Connection对象创建Statement对象 Statement statement = connection.createStatement(); } catch (SQLException e) { e.printStackTrace(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值