【JDBC】数据库增删改查操作的封装

6 篇文章 1 订阅
2 篇文章 1 订阅

目录

1. 前言

2. 准备工作

2.1 ResultSet介绍

2.2 ResultSetMetaData介绍

2.3 ORM思想

3. 增删改操作的封装

3.1 代码封装

3.2 测试

 4. 查询数据的封装

5.封装工具类总结 


1. 前言

在前一篇文章中,我们介绍了如何使用PrepareStatement来进行数据库的增删改查。但是如果不做改进的话,我们每一次进行数据库的增删改查的时候都要重写一遍之前的过程。那么有没有办法可以让我们只写一遍就可以呢?答案就是将那些公共部分封装起来,成为一个工具类,使用时只需要向其中提供必要参数即可。所以我们接下来介绍如何将数据库的增删改查操作封装到一个类中。需要注意的是,下面的内容涉及到泛型、反射,对于不熟悉的读者需要先行了解相关内容。通过这篇文章我们可以深入体会Java面向对象的思想。

2. 准备工作

在正式开始之前我们先介绍一下一些需要使用的API以及ORM思想。

2.1 ResultSet介绍

ResultSet是在我们进行查询操作时,执行完sql语句后用来承接结果集的接口,通过这个接口我们才能对结果集中的数据进行读取。

ResultSet中的常用方法:

  1. boolean next():判断结果集中是否还存在下一条记录,如果有则返回true,没有则返回false同时指针下移。
  2. Xxx getXxx(int columnIndex):获取指针所指向数据对应索引位置的值。
  3. ResultSetMetaData getMetaData():获取结果集的元数据

2.2 ResultSetMetaData介绍

ResultSetMetaData是用来接收结果集的元数据的,比如说结果集中有多少列、每个列的列名等。只有配合ResultSetMetaData我们才能完整的实现对结果集数据的读取。

ResultSetMetaData中常用方法

  1. int getColumnCount():获取结果集中的列数
  2. String getColumnName(int index):获取结果集中索引位置的列名
  3. String getColumnLabel(int index):获取结果集中索引位置的列的别名

2.3 ORM思想

ORM思想是Java面向对象的具体体现,就是将相关事物抽象成一个类,然后事物的一个实例对应一个对象。在我们这篇文章中ORM思想的具体体现如下

  1. 数据库中的一个表对应一个类
  2. 一个字段对应一个属性
  3. 一条记录对应一个对象

3. 增删改操作的封装

3.1 代码封装

对于增删改来说,我们的处理结果没有返回一个结果集,所以我们不需要使用ResultSet来对其进行操作,自然而然的就和查询分开了。

我们封装过程中需要注意的是有哪些是不确定因数,确定了不确定因素后将不确定因素作为方法参数,这样在使用方法时只需要提供具体实参即可。封装步骤如下:

  1. 确定不确定因素:所获取的数据库连接、具体sql语句和sql语句中的占位符个数。
  2. 将不确定因素作为形参出现在方法中:如何确定形参格式见下设计思路。
  3. 构建方法:增删改的步骤为预编译sql语句--->填写占位符--->执行sql语句。

数据库连接是可以通过之前文章中封装的获取数据库连接的方法,其中需要提供的是一个String类型的配置文件名称,所以是String类型的形参;sql语句是String类型;占位符的个数我们不确定所以使用Object类型的可变形参。

具体封装代码如下

package uitl;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import com.mysql.cj.protocol.Resultset;

public class ConnectionUtil {	
	//增删改数据表
	public static void CUDTable(String fileName,Connection con,String sql,Object...obj) throws Exception {		
		Connection connect = null;		
		PreparedStatement ps = null;
		try {
			//获取数据库连接
			connect = getConnection(fileName);
			//预编译sql语句
			ps = connect.prepareStatement(sql);
			//填充占位符
			for(int i=1;i<=obj.length;i++) {
				ps.setObject(i, obj[i-1]);
			}
			//执行sql语句
			ps.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//关闭相关资源
			closeConnection(connect, ps);
		}
	}
}

3.2 测试:

1.向test_table数据表中增加三条数据如下

userpassword
133290123456
105651133290
123456105651

2.将数据修改为如下

userpassword
133290133290
105651105651
123456123456

3.删除user=133290的数据

增加数据:

@Test
	public void test1() {
		String fileName="test.properties";
		Scanner scanner=new Scanner(System.in);
		//增加数据
		for(int i=1;i<=3;i++) {
			System.out.println("账号:");
			Integer user=scanner.nextInt();
			System.out.println("密码:");
			Integer password=scanner.nextInt();
			String sql="insert into test_table(`user`,`password`) values (?,?)";
			ConnectionUtil.CURTable(fileName, sql,user,password);
		}
	}

运行结果

账号:
133290
密码:
123456
操作成功
账号:
105651
密码:
133290
操作成功
账号:
123456
密码:
105651
操作成功

sql查询结果

 修改数据和删除数据只是sql语句改变,其他不变

 4. 查询数据的封装

由于查询在执行完sql语句后得到的是一个结果集并没有输出出来,所以我们要将结果集中的数据提取后再输出才行。对于提取数据,我们结合ResultSet和ResultSetMetaData来提取。但是对于提取出来后的承接和输出的方式却是值得我们思考的。

诚然我们可以直接将一个个数据提取出来后再拼接输出,但是Java作为面向对象语言,我们将表中的各个字段都作为类的一个属性,提取出来的数据都封装到一个对象中,这样能更好的体现面向对象的思想。所以查询的步骤如下:

  1. 根据表构建一个类,把表的每个字段作为类的属性。
  2. 依次读取结果集中的每一个字段的值和字段的名(有可能得到的是别名,看查询语句中的具体情境)。
  3. 构建对象承接读取的数据:通过反射将类中与读取字段名相同的属性值设置成读取出来的值。
  4. 如果有多个对象则将对象存储在集合中。
  5. 通过对象输出相应的数据。
package uitl;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;

import com.mysql.cj.protocol.Resultset;

public class ConnectionUtil {	
	//查询数据表
	public static <T> ArrayList<T> ReferTable(String fileName,Class<T> clazz,String sql,Object...object) throws Exception {
		Connection connection=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			//创建集合对象用来存储对象
			ArrayList<T> arrayList=new ArrayList<T>();
			//获取连接
			connection = getConnection(fileName);
			//预编译sql语句
			ps = connection.prepareStatement(sql);
			//填充占位符
			for(int i=1;i<=object.length;i++) {
				ps.setObject(i, object[i-1]);
			}
			//执行sql语句获取ResultSet对象
			rs = ps.executeQuery();
			//获取结果集的元数据
			ResultSetMetaData rsmd=rs.getMetaData();
			//获取列数
			int column=rsmd.getColumnCount();
			//读取数据构造对象
			while(rs.next()) {
				//创建对象
				T t=clazz.newInstance();
				//读取数据,并将对象的属性值修改为读取的数据
				for(int i=1;i<=column;i++) {
					//获取结果集中列名
					String columnName=rsmd.getColumnLabel(i);
					//获取结果集中列值
					Object columnValue=rs.getObject(i);
					//将对象中与结果集列名相对应的属性赋值为对应的值
					Field field=clazz.getDeclaredField(columnName);
					field.setAccessible(true);
					field.set(t,columnValue);
				}
				//将对象添加到集合中
				arrayList.add(t);
			}
			//返回集合值
			return arrayList;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//关闭相关资源
			closeConnection(connection, ps, rs);
		}
		return null;
	}
}

示例

查询test_table中账号为133290和105651的数据

查询数据

package curd;

public class Test_Table {
	int identification;
	int cipher;
	@Override
	public String toString() {
		return "identification=" + identification + ", cipher=" + cipher;
	}
	public int getIdentification() {
		return identification;
	}
	public void setIdentification(int identification) {
		this.identification = identification;
	}
	public int getCipher() {
		return cipher;
	}
	public void setCipher(int cipher) {
		this.cipher = cipher;
	}
}


@Test
	public void test4() throws Exception {
		//查询数据
		/*获取配置文件名*/
		String fileName="test.properties";
		/*查询语句*/
		String sql="select `user` as identification,`password` as cipher from test_table where `user`=? or `user`=?";
		Scanner scanner=new Scanner(System.in);
		/*占位符*/
		Integer user1=133290;
		Integer user2=123456;
		ArrayList<Test_Table> list= ConnectionUtil.ReferTable(fileName, Test_Table.class, sql, user1,user2);
		System.out.println(list);
	}

查询结果如下

[identification=123456, cipher=123456, identification=133290, cipher=133290]

5.封装工具类总结 

最终完成的JDBC工具类包括如下功能:通过输入配置文件名获取数据库连接、关闭数据库连接、提供相应的条件完成增删改查。总的工具类代码如下,建议保存起来,下次可以直接使用,省去很多麻烦。

6.注意点

不能用占位符代替表名!!!!!!!!(博主已经吃过亏了)

  • 25
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值