面向对象程序设计语言的四大特点之一就是:封装。正如Java,其在固定的类中封装了很多方法,这些方法我们不用管它的底层是怎么实现的,只要知道它如何用就可以进行编程。所以,我们在平时项目的过程中也应该考虑到这一点,从而减少代码量,达到应有的目的。
以下代码是对数据库的一系列操作进行了封装,封装成了一个名字叫做DButil的类,在这个类中存在很多方法可以去对数据库进行一系列的操作。
其中最主要的是这个类里面的query方法,即查询方法,在访问数据库时增删改这三个操作其实可以统称为一个,因为他们不需要返回结果集,只需要把相对应的sql语句发送到数据库去执行。但是查询方法是要把查询的结果作为一个结果集返回给用户的。然而如果每次都使用ResultSet对象是不会对结果进行长时间存储的,所以说每次都要去查询一次,并且对ResultSet对象这一结果集进行一系列操作也不方便,所以在以下代码中没一次查数据库都有一个类与之对应。
然后利用Java的反射机制通过查询出来的结果创建一个与这个类相对应的一个实例,其数据便存在了类的对象中,然后再把这个实例存储在list中,作为用户对该方法调用后的返回,对list集合操作起来比对ResultSet对象操作起来容易得多。其中,一张表对应一个类,并且表中列名要与类中相对应的属性名保持一致。这一特点在代码中也是可以看出的,因为利用反射机制创建对象的实例时,用到的fieldname便是从数据库中查询出的列名。
具体代码如下:
package com.util;
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.List;
import java.util.Vector;
public class DButil {
//实例化连接池(创建连接池的好处:想用的时候直接去取,而不是每次想用的时候再去重新创建,这样可以减小内存开销)
public static Vector<Connection> connectionPool = new Vector<Connection>();
//初始化连接池
static{
try {
Class.forName("com.mysql.jdbc.Driver");//加载驱动
for(int i = 0;i<10;i++){//初始化10个连接的原因:假设同时最多有10处用此DButil取连接(如果大于10的话,还要把这个数增大)
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3307/shengshiliandong", "root", "admin");//得到连接对象(由这行代码可知:一个数据库对应一个dbutil)
connectionPool.add(connection);
}
}catch (Exception e) {
e.printStackTrace();
}
}
//取连接
public static Connection getConnection(){
Connection connection = connectionPool.get(0);
connectionPool.remove(0);//根据java.util.Vector类的源代码可知:remove(0)执行后,后面的数据会自动向前移动将其补上
return connection;
}
//释放连接
public static void releaseConnection(Connection connection){
connectionPool.add(connection);
}
//增删改
public static void zsg(String sql,Object...objects){//Objects...为不定数组
Connection connection = null;
try {
connection = getConnection();//取连接进而得到连接对象(相当于将Java与数据库之间的“桥”搭建起来)
PreparedStatement preparedStatement = connection.prepareStatement(sql);//相当于new出来了一个过桥送信的人
if(objects != null){//给sql语句中的问号赋值
for(int i = 0;i<objects.length;i++){
preparedStatement.setObject(i+1,objects[i] );
}
}
int n = preparedStatement.executeUpdate();//将sql语句发送到数据库执行(相当于让送信人出发去送信)
} catch (SQLException e) {
e.printStackTrace();
}finally{
releaseConnection(connection);//释放连接
}
}
//查询
public static List query(Class c,String sql,Object...objects){
List list = new ArrayList();
Connection connection = getConnection();//取连接进而得到连接对象(相当于将Java与数据库之间的“桥”搭建起来)
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);//相当于new出来了一个过桥送信的人
if(objects != null){//给sql语句中的?号赋值
for(int i = 0;i<objects.length;i++){
preparedStatement.setObject(i+1, objects[i]);//给sql语句中的sql语句赋值
}
}
ResultSet resultSet = preparedStatement.executeQuery();//发送SQL语句,并返回结果集
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();//得到resultSet对象相对应的resultSetMetaData对象
int count = resultSetMetaData.getColumnCount();//得到ResultSet对象的总列数(后面的循环语句中会使用到)
while(resultSet.next()){//外层while循环用于控制“行”
Object object = c.newInstance();//创建c所代表的类的新实例
for(int i = 0;i<count;i++){//for循环用于控制“列”
String fieldName = resultSetMetaData.getColumnLabel(i+1);//获取打印输出和显示的指定的第i+1列的标题
Field field = c.getDeclaredField(fieldName);//返回一个 Field 对象,该对象反映此 Class 对象所表示的类的指定已声明字段
field.setAccessible(true);//值为 true用于指示反射的对象在使用时应该取消 Java 语言访问检查,即使得field可以访问此class对象所对应的类的私有化属性
field.set(object, resultSet.getObject(i+1));//将指定对象变量object上此 Field 对象表示的字段设置为指定的新值resultSet.getObject(i+1)
}
list.add(object);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
releaseConnection(connection);//释放连接
}
return list;//返回储存着对象实例的list集合
}
}