【Java】利用单例模式、可变参数优化Java操作Mysql数据库、JDBC代码的写作

本文没有任何新的内容,只是设置一个Java操作Mysql数据库,让代码写得更好而已。

如同《【Java】Java中对Mysql数据库的增删改查、Java的System类》(点击打开链接)一样,工程极其简单,引入操作Mysql数据库相应的jar之后就一个DB类,


下文将对test数据库中的一张usertable表进行操作,usertable表的结构如下:


这张表用来做例子都用烂了,就ID、用户名、密码3个字段,里面的结构如下:


之后,我们建立如下的Db.java:

import java.sql.*;
import java.util.*;

public class Db {
	// 一、单例初始化连接
	private Connection con;

	// 以下代码,保证该类只能有一个实例
	private Db() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			// 其中test是我们要链接的数据库,user是数据库用户名,password是数据库密码。
			// 3306是mysql的端口号,一般是这个
			// 后面那串长长的参数是为了防止乱码,免去每次都需要在任何语句都加入一条SET NAMES UTF8
			String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true";
			String user = "pc";
			String password = "admin";
			con = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
	} // 私有无参构造方法

	// 在自己内部定义自己的一个实例,只供内部调用
	private static Db db = null;

	// 这个类必须自动向整个系统提供这个实例对象
	// 这里提供了一个供外部访问本class的静态方法,可以直接访问
	public static Db getInstance() {
		if (db == null) {
			db = new Db();
		}
		return db;
	}

	// 二、查询
	// 使用SQL查询,查询的结果是一个结果集(视图)
	public List<Object[]> getBySql(String sql) {
		List<Object[]> result_list = new ArrayList<Object[]>();
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				ResultSetMetaData md = rs.getMetaData();
				int columnCount = md.getColumnCount();
				Object[] row_data_set = new Object[columnCount];
				for (int i = 1; i <= columnCount; i++) {
					row_data_set[i - 1] = rs.getObject(i);
				}
				result_list.add(row_data_set);
			}
			return result_list;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	// 查询sql语句带参数的情况
	public List<Object[]> getBySql(String sql, Object[] param) {
		List<Object[]> result_list = new ArrayList<Object[]>();
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			for (int i = 0; i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				ResultSetMetaData md = rs.getMetaData();
				int columnCount = md.getColumnCount();
				Object[] row_data_set = new Object[columnCount];
				for (int i = 1; i <= columnCount; i++) {
					row_data_set[i - 1] = rs.getObject(i);
				}
				result_list.add(row_data_set);
			}
			return result_list;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	// 使用SQL查询,查询的结果是唯一
	private Object getBySql_result_unique(String sql) {
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			rs.next();
			return rs.getLong(1);
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	// 查询sql语句带参数的情况
	public Object getBySql_result_unique(String sql, Object[] param) {
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			for (int i = 0; i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			ResultSet rs = ps.executeQuery();
			rs.next();
			return rs.getLong(1);
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	// 三、增删改
	// insert、update、delete等修改数据库的语句
	public void setBySql(String sql) {
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// sql语句带参数的情况
	public void setBySql(String sql, Object[] param) {
		try {
			PreparedStatement ps = con.prepareStatement(sql);
			for (int i = 0; i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// 析构函数,中断数据库的连接
	protected void finalize() throws Exception {
		if (!con.isClosed() || con != null) {
			con.close();
		}
	}

	public static void main(String[] args) {
		Db db = Db.getInstance();
		System.out.println("id大于1的结果集:");
		List<Object[]> result_list = db.getBySql(
				"select * from usertable where id>?", new Object[] { 1 });
		for (int i = 0; i < result_list.size(); i++) {
			Object[] row = result_list.get(i);
			for (int j = 0; j < row.length; j++) {
				System.out.print(row[j] + ",");
			}
			System.out.println();
		}
		System.out.println();
		long result = (long) db
				.getBySql_result_unique("select count(*) from usertable");
		System.out.println("usertable表所含有的项数:"+result);
		// 插入示例:db.setBySql("insert into usertable(username,password) values(?,?)",new Object[]{"username","password"});
	}

}

此程序首先利用《【Java】单例模式》( 点击打开链接)让数据库连接的单例化,不至于调用一次数据库连接类就多一次数据库连接,增加不必要的压力。

之后,利用《【Java】JDK1.5以后新型的泛型参数传递方法Object...args》(点击打开链接)中可变参数为数据库的增删改查新建开辟可变参数查询。

注意的主函数中的对增删改查的实施,无论这个查询是带参数,还不是不带参数同样能够应付。

利用到JDBC自带的PreparedStatement旗下的setObject组织语句,这样一来可以应付各种传过来的SQL语句,带有不同参数的情况,二来最关键的事情,可以应付绝大多数情况的SQL注入的情况,不用自己再写相应的SQL注入过滤方法。

PreparedStatement ps = con.prepareStatement(sql);
for (int i = 0; i < param.length; i++) {
	ps.setObject(i + 1, param[i]);
}
ResultSet rs = ps.executeQuery();
其后,由于查询出来的结果集是一样几乘于几的表,我们同样是未知的。

因此,在组织数据的时候,先利用ResultSetMetaData md = rs.getMetaData();int columnCount = md.getColumnCount();获取查询得到的列数,对于每一行的处理,先新建相应列长的Object数组,再利用for循环对于每一行,管它是字符串还是数字,将每一列的结果放入这个Object数组,注意到ResultSet的getObject方法索引是从1开始的,而Java中的任何数组索引都是从0开始的,因此i请自行控制好。之后再把这个Object数组输入,压入一个存Object的List中。

最后这个方法返回这个List给调用者,就OK。

while (rs.next()) {
	ResultSetMetaData md = rs.getMetaData();
	int columnCount = md.getColumnCount();
	Object[] row_data_set = new Object[columnCount];
	for (int i = 1; i <= columnCount; i++) {
		row_data_set[i - 1] = rs.getObject(i);
	}
	result_list.add(row_data_set);
}

对于查询仅一个数字,没有返回结果的处理非常简单,这里就不再赘述。

因此上述的整个程序的运行结果如下:


本类还可以配合《【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统》(点击打开链接)应用到Javaweb中Jsp+Servlet+JDBC的场合。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值