JDBC连接Mysql数据库 (使用Java反射进行优化)

一、下载mysql驱动

   下载mysql驱动教程链接:https://jingyan.baidu.com/article/c275f6ba6bf785e33d756707.html

二、把下载好的mysql驱动复制粘贴到项目的lib文件夹下 (如果没有lib文件夹,就在项目下新建一个lib文件夹),然后选中mysql驱动包鼠标右键选择 Build Path → Add to Build Path

三、优化 JDBC连接Mysql数据库的 增加、删除和修改方法

   3.1、首先让我们来看一下优化前的添加、修改和删除方法 有什么缺点

  3.1.1、创建一个Student实体类,用于JDBC连接Mysql数据库

package com.mysql.pojo;

public class Student implements Serializable{

	private Integer id;
	private String name;
	private String sex;
	

	public Student() {}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex + "]";
	}
	
}

       

  3.1.2、添加数据方法

public void add(Student student) {
		Connection conn = null;
		PreparedStatement stmt = null;
		
		try {
			
			// 1、注册驱动 
			Class.forName("com.mysql.jdbc.Driver");
			
			String url = "jdbc:mysql://localhost:3306/mytest";  //连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; //mysql数据库账号
			String password = "123456"; //mysql数据库密码
			
			//2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			//3、编写mysql语句
			String sql = "insert into student(id,name,sex) values(?,?,?)";
			stmt = conn.prepareStatement(sql);
			//4、替换mysql语句中的问号 (注意:下标是从1开始的)
			stmt.setObject(1, student.getId());
			stmt.setObject(2, student.getName());
			stmt.setObject(3, student.getSex());
		
			//5、执行executeUpdate
			int executeUpdate = stmt.executeUpdate();

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			
			//6、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}
				
				conn = null;
			}
		}

	}

3.1.3、修改数据方法

public void update(Student student) {
		Connection conn = null;
		PreparedStatement stmt = null;

		try {

			// 1、注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/mytest"; // 连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; // mysql数据库账号
			String password = "123456"; // mysql数据库密码

			// 2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			// 3、编写mysql语句
			String sql = "update student set name=?, sex=? where id=?";
			stmt = conn.prepareStatement(sql);
			// 4、替换mysql语句中的问号 (注意:下标是从1开始的)
			stmt.setObject(1, student.getName());
			stmt.setObject(2, student.getSex());
			stmt.setObject(3, student.getId());

			// 5、执行executeUpdate
			int executeUpdate = stmt.executeUpdate();

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			// 6、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				conn = null;
			}
		}

	}

3.1.4、删除数据方法

public void delete(Integer id) {
		Connection conn = null;
		PreparedStatement stmt = null;

		try {

			// 1、注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/mytest"; // 连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; // mysql数据库账号
			String password = "123456"; // mysql数据库密码

			// 2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			// 3、编写mysql语句
			String sql = "delete from student where id=?";
			stmt = conn.prepareStatement(sql);
			// 4、替换mysql语句中的问号 (注意:下标是从1开始的)
			stmt.setObject(1, id);
			
			// 5、执行executeUpdate
			int executeUpdate = stmt.executeUpdate();
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			// 6、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				conn = null;
			}
		}

	}

   3.2、通过对比发现,添加、修改和删除方法,除了方法参数、mysql数据库语句和替换mysql语句中的问号不同,其他步骤都是相同的,这时我们可以对这三个方法进行提取和优化,使其变成一个方法,其优化之后的结果如下:

   3.2.1、创建一个jdbc.properties文件,在文件中添加如下信息:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytest
name=root
password=123456

   

3.2.2、优化之后的MysqlDemo类

package com.mysql.demo;

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

public class MysqlDemo {

	private static Properties properties = null;
	private static Connection connection = null;
	private static PreparedStatement statement = null;
	private static ResultSet resultSet = null;

	static {

		try {
			// 1.注册驱动
			InputStream resourceAsStream = MysqlDemo.class.getClassLoader().getResourceAsStream("jdbc.properties");
			properties = new Properties();
			properties.load(resourceAsStream);
			String property = properties.getProperty("className");

			Class.forName(property);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 获取与mysql数据库的连接
	public static Connection getConnection() {
		try {
			// 2.获取连接
			String url = properties.getProperty("url");
			String user = properties.getProperty("user");
			String password = properties.getProperty("password");
			return DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

        /*
         * 添加、修改和删除方法优化 
         * 返回值为Integer:影响行数
         * 参数: 
         *   sql:Mysql数据库查询语句 
         *   array:可变参数
         */
	public static Integer Update(String sql, Object... array) {
		try {
			connection = MysqlDemo.getConnection();
			statement = connection.prepareStatement(sql);
			for (int i = 0; i < array.length; i++) {
				statement.setObject(i + 1, array[i]);
			}
			return statement.executeUpdate();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			closeAll(null, statement, connection);
		}
	}

	// 关闭资源
	public static void closeAll(ResultSet resultSet, PreparedStatement statement, Connection connection) {
		// 关闭resultSet
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				resultSet = null;
			}

		}

		// 关闭statement
		if (statement != null) {
			try {
				statement.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				statement = null;
			}

		}

		// 关闭connection
		if (connection != null) {
			try {
				connection.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				connection = null;
			}

		}

	}

}

   3.2.3、使用方式如下:

public static void main(String[] args) {

		Student student = new Student();
		student.setId(1);
		student.setName("李四");
		student.setSex("男");

		// ------------添加数据操作------------
		String addSql = "insert into student(id,name,sex) values(?,?,?)";
		MysqlDemo.Update(addSql, student.getId(), student.getName(), student.getSex());

		// ------------修改数据操作------------
		student.setName("王五");
		student.setSex("女");
		String updateSql = "update student set name=?, sex=? where id=?";
		MysqlDemo.Update(updateSql, student.getId(), student.getName(), student.getSex());

		// ------------删除数据操作------------
		String deleteSql = "delete from student  where id=?";
		MysqlDemo.Update(updateSql, student.getId());
}

四、优化 JDBC连接Mysql数据库的 查询方法

   4.1、由于查询比较复杂,查询的返回结果可以是一个对象、一个对象集合、一个字段集合或者一个字段(例如查询count(*) ),首先让我们来看一下优化前的查询方法,有什么缺点

      4.1.1、查询数据方法,并返回一个对象

public Student select(Integer id) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;

		try {

			// 1、注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/mytest"; // 连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; // mysql数据库账号
			String password = "123456"; // mysql数据库密码

			// 2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			// 3、编写mysql语句
			String sql = "select * from student where id=?";
			stmt = conn.prepareStatement(sql);
			// 4、替换mysql语句中的问号 (注意:下标是从1开始的)
			stmt.setObject(1, id);
			// 5、执行executeQuery
			resultSet = stmt.executeQuery();

			// 6、创建Student实体类对象
			Student student = new Student();

			if (resultSet.next()) {
				student.setId(resultSet.getInt("id"));
				student.setName(resultSet.getString("name"));
				student.setSex(resultSet.getString("sex"));
			}

			return student;

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			// 6、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				conn = null;
			}

			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				resultSet = null;
			}
		}

	}

     4.1.2、查询数据方法,并返回一个对象的集合

public List<Student> select(String sex) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;

		try {

			// 1、注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/mytest"; // 连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; // mysql数据库账号
			String password = "123456"; // mysql数据库密码

			// 2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			// 3、编写mysql语句
			String sql = "select * from student where sex=?";
			stmt = conn.prepareStatement(sql);
			// 4、替换mysql语句中的问号 (注意:下标是从1开始的)
			stmt.setObject(1, sex);
			// 5、执行executeQuery
			resultSet = stmt.executeQuery();

			// 6、声明Student实体类对象
			Student student = null;
           
			//7、创建对象集合
			ArrayList<Student> list = new ArrayList<>();
			
			while (resultSet.next()) {
				student = new Student();
				student.setId(resultSet.getInt("id"));
				student.setName(resultSet.getString("name"));
				student.setSex(resultSet.getString("sex"));
				
				//8、添加到对象集合中
				list.add(student);
			}

			return list;

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			// 9、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				conn = null;
			}

			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				resultSet = null;
			}
		}

	}

       4.1.3、查询数据方法,并返回一个字段集合

public List<String> select() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;

		try {

			// 1、注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/mytest"; // 连接数据库的url 格式:协议 ://主机名:端口号/数据库名称
			String user = "root"; // mysql数据库账号
			String password = "123456"; // mysql数据库密码

			// 2、获取与mysql数据库的连接 Connection
			conn = DriverManager.getConnection(url, user, password);
			// 3、编写mysql语句
			String sql = "select name from student";
			stmt = conn.prepareStatement(sql);

			// 4、执行executeQuery
			resultSet = stmt.executeQuery();

			// 5、创建String数据类型集合
			ArrayList<String> list = new ArrayList<>();

			while (resultSet.next()) {
				String num = resultSet.getString("name");
				// 6、添加到String数据类型集合中
				list.add(num);
			}

			return list;

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

			// 6、释放资源
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				stmt = null;
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				conn = null;
			}

			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException sqlex) {
					throw new RuntimeException(sqlex);
				}

				resultSet = null;
			}
		}

	}

  4.2、通过对比发现,查询的三个方法,除了方法参数、mysql数据库语句、替换mysql语句中的问号、resultSet结果集处理和返回值不同,其他步骤都是相同的,这时我们可以对这三个方法进行提取和优化,使其变成一个方法,其优化之后的结果如下:

   4.2.1、创建一个jdbc.properties文件,在文件中添加如下信息:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytest
name=root
password=123456

   4.2.2、优化之后的MysqlDemo类

package com.mysql.demo;

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

import com.mysql.dbutil.ResultSetHandler;

public class MysqlDemo {

	private static Properties properties = null;
	private static Connection connection = null;
	private static PreparedStatement statement = null;
	private static ResultSet resultSet = null;

	static {

		try {
			// 1.注册驱动
			InputStream resourceAsStream = MysqlDemo.class.getClassLoader().getResourceAsStream("jdbc.properties");
			properties = new Properties();
			properties.load(resourceAsStream);
			String property = properties.getProperty("className");

			Class.forName(property);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 获取与mysql数据库的连接
	public static Connection getConnection() {
		try {
			// 2.获取连接
			String url = properties.getProperty("url");
			String user = properties.getProperty("user");
			String password = properties.getProperty("password");
			return DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


       /*
        * 查询方法优化 返回值使用Object,来解决返回值不同的问题
        * 参数: 
        *   sql:Mysql数据库查询语句 
        *   handler:resultSet结果集处理接口
        *   array:可变参数
        */
	public static Object Query(String sql, ResultSetHandler handler, Object... array) {

		try {
			connection = MysqlDemo.getConnection();
			statement = connection.prepareStatement(sql);
			for (int i = 0; i < array.length; i++) {
				statement.setObject(i + 1, array[i]);
			}
			resultSet = statement.executeQuery();
			return handler.Handler(resultSet);

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			closeAll(resultSet, statement, connection);
		}

	}

	// 关闭资源
	public static void closeAll(ResultSet resultSet, PreparedStatement statement, Connection connection) {
		// 关闭resultSet
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				resultSet = null;
			}

		}

		// 关闭statement
		if (statement != null) {
			try {
				statement.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				statement = null;
			}

		}

		// 关闭connection
		if (connection != null) {
			try {
				connection.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				connection = null;
			}

		}

	}
}

   4.2.3、resultSet结果集处理接口类

package com.mysql.dbutil;

import java.sql.ResultSet;

public interface ResultSetHandler {

	// 处理resultSet结果集抽象方法
	public abstract Object Handler(ResultSet resultSet);

}

  4.2.4、处理对象的ResultSetHandler接口实现类 --- BeanResultSetHandler

package com.mysql.dbutil;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class BeanResultSetHandler implements ResultSetHandler {

	//字节码文件对象字段
	public Class<?> clazz;

	public BeanResultSetHandler(Class<?> clazz) {
		this.clazz = clazz;
	}

	public Object Handler(ResultSet resultSet) {
		try {
			//通过反射创建实体类对象
			Object object = clazz.newInstance();
			
			//获取此 ResultSet 对象的列的编号、类型和属性。
			ResultSetMetaData metaData = (ResultSetMetaData) resultSet.getMetaData();
			
			//获取此 ResultSet 对象中的列数
			int Columncount = metaData.getColumnCount();
			if (resultSet.next()) {
				for (int i = 0; i < Columncount; i++) {
					//获取指定列的名称
					String name = metaData.getColumnName(i + 1);

					//通过反射获取字段
					Field field = clazz.getDeclaredField(name);
					field.setAccessible(true);
					//设置字段值
					field.set(object, resultSet.getObject(name));
				}
			}

			return object;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

  4.2.5、处理集合的ResultSetHandler接口实现类 --- ListResultSetHandler

package com.mysql.dbutil;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

public class ListResultSetHandler implements ResultSetHandler {

	// 字节码文件对象字段
	public Class<?> clazz;

	public ListResultSetHandler(Class<?> clazz) {
		this.clazz = clazz;
	}

	public Object Handler(ResultSet resultSet) {

		try {
			List<Object> list = new ArrayList<Object>();

			// 获取此 ResultSet 对象的列的编号、类型和属性。
			ResultSetMetaData metaData = (ResultSetMetaData) resultSet.getMetaData();

			// 获取此 ResultSet 对象中的列数
			int Columncount = metaData.getColumnCount();
			Object object = null;

			while (resultSet.next()) {
				// 通过反射创建实体类对象
				object = clazz.newInstance();

				for (int i = 0; i < Columncount; i++) {
					// 获取指定列的名称
					String name = metaData.getColumnName(i + 1);

					// 通过反射获取字段
					Field field = clazz.getDeclaredField(name);
					field.setAccessible(true);
					// 设置字段值
					field.set(object, resultSet.getObject(i + 1));
				}

				list.add(object);
			}

			return list;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

   4.2.6、处理字段集合的ResultSetHandler接口实现类 --- ColumnResultSetHandler

package com.mysql.dbutil;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class ColumnResultSetHandler implements ResultSetHandler {

	// 要查询的字段
	public String str;

	public ColumnResultSetHandler(String str) {
		this.str = str;
	}

	public Object Handler(ResultSet resultSet) {
		try {
			List<Object> list = new ArrayList<Object>();
			while (resultSet.next()) {
				Object object = resultSet.getObject(str);
				list.add(object);
			}
			return list;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

   4.2.7、使用方式如下:

public static void main(String[] args) {

		// ------------查询数据,并返回一个对象集合------------
		String sqlForBean = "select * from student where id=?";
		ResultSetHandler handlerForBean = new BeanResultSetHandler(Student.class);
		Student student = (Student) MysqlDemo.Query(sqlForBean, handlerForBean, 1);

		// ------------查询数据,并返回一个对象集合------------
		String sqlForList = "select * from student where sex=?";
		ResultSetHandler handlerForList = new ListResultSetHandler(Student.class);
		List<Student> list = (List<Student>) MysqlDemo.Query(sqlForList, handlerForList, "男");

		// ------------查询数据,并返回一个字段集合------------
		String sqlForColumn = "select name from student where sex=?";
		ResultSetHandler handlerForColumn = new ColumnResultSetHandler("name");
		List<String> listForColumn = (List<String>) MysqlDemo.Query(sqlForColumn, handlerForColumn, "男");

		// ------------查询数据,并返回一个字段------------
		String sqlForField = "select count(*) from student";
		ResultSetHandler handlerForField = new ColumnResultSetHandler("count(*)");
		List<Integer> listForField = (List<Integer>) MysqlDemo.Query(sqlForField, handlerForField);
		Integer count = listForField.get(0);

	}

           如果有遇到不懂或者有问题时,可以扫描下方二维码,欢迎进群交流与分享,希望能够跟大家交流学习!

                                                             

发布了76 篇原创文章 · 获赞 253 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/qq_39135287/article/details/93786071
今日推荐