JDBC进化史(四)优化之:数据传递优化

在上一篇中,我们完成了JDBC的基本添加、删除操作,同时也发现了两个问题:
在使用完JDBC资源后,如果不关闭,可能会造成内存泄露的问题。
当需要添加的数据或需要修改的数据量很多时,通过pstm.setObject(, );方法这样一个个输入显然是不现实的,效率太低了!那么,我们是否可以采用其他方式提高效率呢?
我们可不可以定义一个数组用于储存我们需要修改的数据,当进行JDBC操作时,将这个数组导入操作方法,一口气完成操作呢?

一、引入:动态参数的使用

JDK1.5之后新增了动态参数的使用方法,下边仅给出简单示例:

public class ParameterTest 
{
	public static void PrintStudentName(String...val)
	{
		int i = 0;
		//在这里使用了动态参数,使用String name获取val的值,只要val还有下一个值,就依次给name赋值
		 for(String name:val)
		 {
			 i++;
			 System.out.println("第"+i+"次获取的值为:"+name);
		 }
	}
	
	public static void main(String[] args) 
	{
		ParameterTest.PrintStudentName("张三","李四","王五","赵六");
	}
}

可以得到输出结果

第1次获取的值为:张三
第2次获取的值为:李四
第3次获取的值为:王五
第4次获取的值为:赵六

二、优化尝试1

假设我们想要尝试执行这样一条sql语句:

INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)
       VALUES(S_STU.NEXTVAL,'葫芦娃',TO_DATE('1900-9-9','YYYY-MM-DD'),0,'那时还没考试');

之前提供的方法是这样的:
StudentServices.java

package com.whm.services;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class StudentServices 
{
	//1.添加学生
	public void addStudent()throws Exception
	{
		//1.定义连接串url
		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
		//2.通过驱动管理器匹配url,创建连接
		Connection conn = DriverManager.getConnection(url, "admin", "admin1234");
		//3.定义sql
		StringBuilder sql = new StringBuilder()
				.append("INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)")
				.append("       VALUES(S_STU.NEXTVAL,?,TO_DATE(?,'YYYY-MM-DD'),?,?)");
		//4.预编译sql
		PreparedStatement pstm = conn.prepareStatement(sql.toString());
		//5.参数赋值
		pstm.setObject(1, "葫芦娃");
		pstm.setObject(2, "1900-9-9");
		pstm.setObject(3, "0");
		pstm.setObject(4, "那时还没考试");
		//6.执行sql
		int	tag = pstm.executeUpdate();
		System.out.println(tag);
	}
}

StudentServicesTest.java

package test;

import com.whm.services.StudentServices;

public class StudentServicesTest 
{
	public static void main(String[] args) 
	{
		try
		{
			StudentServicesTest.addStudentTest();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	//测试添加学生
	public static void addStudentTest()throws Exception
	{
		StudentServices services = new StudentServices();
		services.addStudent();
	}
}

下边通过动态参数调用,减少了pstm.setObject()方法的使用次数,同时,使得测试方法中的调用更加便捷

//添加学生
	public void addStudent(Object...val)throws Exception
	{
		//1.定义连接串url
		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
		//2.通过驱动管理器匹配url,创建连接
		Connection conn = DriverManager.getConnection(url, "admin", "admin1234");
		//3.定义sql
		StringBuilder sql = new StringBuilder()
				.append("INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)")
				.append("       VALUES(S_STU.NEXTVAL,?,TO_DATE(?,'YYYY-MM-DD'),?,?)");
		//4.预编译sql
		PreparedStatement pstm = conn.prepareStatement(sql.toString());
		//5.参数赋值
		int index = 1;
		for(Object param:val)
		{
			pstm.setObject(index++, param);
		}
		//6.执行sql
		int	tag = pstm.executeUpdate();
		System.out.println(tag);
	}

测试方法中:

//测试添加学生
	public static void addStudentTest()throws Exception
	{
		
		StudentServices services = new StudentServices();
		
		/**
		 * 创建一个Object数组,用于提供我们想要传递的值
		 * 	    带上sql语句用于参照对应:
		 * 	  INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)
		 */
		Object val[] = {"葫芦娃","1900-9-9","0","那时还没考试"};
		//将值传入方法
		services.addStudent(val);
	}

在addStudent()方法中得到一个参数,同时修改了步骤5

三、优化尝试2

观察我们书写的代码可知:
1.内存泄露问题依旧没有解决
2.每次进行JDBC操作时,都需要书写步骤1和步骤2

于是可以想办法对代码进行改进:
先解决内存泄露问题吧,这个简单,在程序结束后将其关闭即可,修改后的代码如下:

	//添加学生
	public void addStudent(Object...val)throws Exception
	{
		//1.定义JDBC变量
		Connection conn = null;
		PreparedStatement pstm = null;
		try
		{
			//2.定义连接串url
			String url = "jdbc:oracle:thin:@localhost:1521:orcl";
			//3.通过驱动管理器匹配url,创建连接
			conn = DriverManager.getConnection(url, "admin", "admin1234");
			//4.定义sql
			StringBuilder sql = new StringBuilder()
					.append("INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)")
					.append("       VALUES(S_STU.NEXTVAL,?,TO_DATE(?,'YYYY-MM-DD'),?,?)");
			//5.预编译sql
			pstm = conn.prepareStatement(sql.toString());
			//6.参数赋值
			int index = 1;
			for(Object param:val)
			{
				pstm.setObject(index++, param);
			}
			//7.执行sql
			int	tag = pstm.executeUpdate();
			System.out.println(tag);
		}
		finally//在此处销毁资源
		{
			pstm.close();
			conn.close();
		}
	}

四、优化尝试3

实际上,目前还存在大量重复代码,每个操作都需要创建连接、销毁资源,我们也想办法将其封装起来。
我在之前创建的工具目录com.whm.system.db目录下创建了一个新文件:DBUtils.java。
在此文件中书写一些必要的步骤,同时考虑异常问题
DBUtils.java

package com.whm.seystem.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

//JDBC Utils 类
public class DBUtils 
{
	//获取数据库连接
	public static Connection getConnection()throws Exception
	{
		//1.定义连接url
		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
		//2.通过驱动管理器匹配url,创建连接
		Connection conn = DriverManager.getConnection(url, "admin", "admin1234");
		//3.带出连接对象
		return conn;
	}
	
	
	public static void close(PreparedStatement pstm)
	{
		try
		{
			if( pstm!= null)
			{
				pstm.close();
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public static void close(Connection conn)
	{
		try
		{
			if( conn!= null)
			{
				conn.close();
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
}

那么,我们就可以调用这个DBUtils工具类
StudentServices.java

package com.whm.services;

import java.sql.Connection;
import java.sql.PreparedStatement;
import com.whm.seystem.db.DBUtils;

public class StudentServices 
{
	//添加学生
	public void addStudent(Object...val)throws Exception
	{
		//1.定义JDBC变量
		Connection conn = null;
		PreparedStatement pstm = null;
		try
		{
			//2.创建连接
			conn = DBUtils.getConnection();
			//3.定义sql
			StringBuilder sql = new StringBuilder()
					.append("INSERT INTO STUDENT(STUID,SNAME,SDATE,SCORE,MEMO)")
					.append("       VALUES(S_STU.NEXTVAL,?,TO_DATE(?,'YYYY-MM-DD'),?,?)");
			//4.预编译sql
			pstm = conn.prepareStatement(sql.toString());
			//5.参数赋值
			int index = 1;
			for(Object param:val)
			{
				pstm.setObject(index++, param);
			}
			//6.执行sql
			int	tag = pstm.executeUpdate();
			System.out.println(tag);
		}
		finally//在此处销毁资源
		{
			DBUtils.close(pstm);
			DBUtils.close(conn);
		}
	}
}

至此,我们已经完成了传递数据和连接的初步优化

五、新的思考,站在客户角度考虑

1、在许多公司的内部,为了保证数据的安全性,定期会修改公司的内部账号,数据库账号密码也不例外。那么,我们在给客户设计程序的时候,如果像之前这样将用户名密码直接写在代码中,是十分不利于客户使用的。并且将代码交给客户也是存在很大风险的一件事。因此,我们需要找到一个方法来解决这个问题。
2、客户对于操作后,executeUpdate()返回影响了几行数据的这种结果可能并不买账。我们需要一个更直观的操作结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值