手写MySQL的JDBC工具类,实现对任何单个数据表的增删改查

数据表对应的实体类(没有功能方法)

注意:

实体类的类名与数据表的表名相对应
属性名与数据表的字段名相对应
属性类型(必须是对应的包装类类型,后面获取字段类型获取的也是包装类类型)与数据表的字段类型相对应

本工具类仅适用于单表增删改查

package com.imooc.test;

import java.sql.Date;
/**
 * 
 * 实体类的类名与数据表的表名相对应
 * 属性名与数据表的字段名相对应
 * 属性类型与数据表的字段类型相对应
 * @author Mr_249
 *
 */
public class Student {
	private Integer sid;//学生编号
	private String sname;//学生名字
	private Date sage;//学生的出生日期
	private String ssex;//学生性别
	
	//hasnCode()和equals()方法
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((sage == null) ? 0 : sage.hashCode());
		result = prime * result + ((sid == null) ? 0 : sid.hashCode());
		result = prime * result + ((sname == null) ? 0 : sname.hashCode());
		result = prime * result + ((ssex == null) ? 0 : ssex.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (sage == null) {
			if (other.sage != null)
				return false;
		} else if (!sage.equals(other.sage))
			return false;
		if (sid == null) {
			if (other.sid != null)
				return false;
		} else if (!sid.equals(other.sid))
			return false;
		if (sname == null) {
			if (other.sname != null)
				return false;
		} else if (!sname.equals(other.sname))
			return false;
		if (ssex == null) {
			if (other.ssex != null)
				return false;
		} else if (!ssex.equals(other.ssex))
			return false;
		return true;
	}
	//属性的setter和getter方法
	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public Date getSage() {
		return sage;
	}
	public void setSage(Date sage) {
		this.sage = sage;
	}
	public String getSsex() {
		return ssex;
	}
	public void setSsex(String ssex) {
		this.ssex = ssex;
	}
	//toString()方法
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", sage=" + sage + ", ssex=" + ssex + "]";
	}
	//构造方法
	public Student(Integer sid, String sname, Date sage, String ssex) {
		super();
		this.sid = sid;
		this.sname = sname;
		this.sage = sage;
		this.ssex = ssex;
	}
	public Student() {
		super();
		
	}
	
}

增删改查工具类和配置文件

db.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/d_student
user=root
password=123456
package com.imooc.test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
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.Properties;

public class DML_DQLUtil {
	/*
	 * jdbc变量
	 */
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
	/*
	 * 构造器私有,不允许外部创建对象,外部只能够通过类名调用本类的方法
	 */
	private DML_DQLUtil() {
		
	}
	
	/*
	 * 静态代码块为jdbc变量赋值
	 * 因为静态代码块最先执行,所以调用executeQuery()方法时,
	 * 该方法内部的jdbc变量就完成了赋值操作
	 */
	static {
		InputStream in=null;
		try {
			in=DQLUtil.class.getResourceAsStream("/db.properties");//动态获取文件的地址,不需要写绝对路径
			Properties pr=new Properties();
			pr.load(in);//加载文件内容,加载成键值对
			/*
			 * jdbc变量赋值
			 */
			driver=pr.getProperty("driver");
			url=pr.getProperty("url");
			user=pr.getProperty("user");
			password=pr.getProperty("password");
			//加载驱动,静态代码块只执行一次,驱动只加载一次(加载驱动很耗性能的)
			Class.forName(driver);
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}finally {
			//关流
			try {
				if(in!=null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/*
	 * 获取Connection连接的方法,由于查询和增删改都需要创建连接,有冗余代码
	 * 我们可以将冗余代码封装成一个方法
	 */
	public static Connection getConnection() {
		Connection con=null;
		try {
			con=DriverManager.getConnection(url, user, password);//获取连接
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return con;	
	}

	/*
	 * 本类的作用是执行SQL查询语句,并将查询结果的每一条封装在对应的对象中
	 * 然后将对象封装在集合中,并将该集合返回
	 * 
	 * 泛型方法,接收任意类型的对象
	 */
	public static boolean executeDML(String sql,Object...objs) {
		/*
		 * 声明配置信息变量
		 */
		Connection con = null;
		PreparedStatement ps =null;
		//返回的结果
		int result=0;
		try {
			con = DML_DQLUtil.getConnection();//创建连接
			ps = con.prepareStatement(sql);//创建PrepareStatement对象
			/*
			 * 关闭MySQL的自动提交事务,改为手动提交
			 */
			con.setAutoCommit(false);
			/*
			 * 如果SQL语句中有占位符的话,就需要用户给占位符传值
			 */
			if(objs!=null) {
				for(int i=0;i<objs.length;i++) {
					ps.setObject((i+1), objs[i]);
				}
			}
			result=ps.executeUpdate();//执行SQL语句
			/*
			 * SQL语句执行完,提交事务
			 */
			con.commit();
		} catch (SQLException e) {
			/*
			 * 如果try块中报错,立马回滚事务
			 */
			try {
				con.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			//关流
			try {
				if(ps!=null)
					ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(con!=null)
					con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return result==1?true:false;//将执行结果返回	
	}
	/*
	 * 本类的作用是执行SQL查询语句,并将查询结果的每一条封装在对应的对象中
	 * 然后将对象封装在集合中,并将该集合返回
	 * 
	 * 泛型方法,接收任意类型的对象
	 */
	public static <T> List<T> executeDQL(String sql,T t,Object...objs){
		List<T> list=null;
		/*
		 * 声明配置信息变量
		 */
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet rs =null;
		try {
			con = DML_DQLUtil.getConnection();//创建连接
			ps=con.prepareStatement(sql);//封装SQL
			/*
			 * 给SQL语句的占位符传值
			 */
			if(objs!=null){
				for(int i=0;i<objs.length;i++){
					ps.setObject((i+1),objs[i]);
				}	
			}		
			
			rs = ps.executeQuery();//执行SQL
			/*
			 * 
			 */
			ResultSetMetaData rm = rs.getMetaData();//rm对象中存储了结果表中的字段的名字和字段的java类型()包装类类型
			int count = rm.getColumnCount();//获取列的数量
			
			
			/*
			 * 将查询到的信息封装在对象中,再将对象加入集合中
			 */
			list=new ArrayList<>();
			while(rs.next()) {
				Class cla = t.getClass();
				T newInstance = (T)cla.newInstance();//获取T的对象
				/*
				 * 有多少个字段循环就会执行多少次
				 */
				for(int i=0;i<count;i++) {
					String columnName = rm.getColumnName(i+1);//拿到字段的名字
					String methodName="set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);//拿到相应属性的setter方法名
					String fieldType=rm.getColumnClassName(i+1);//拿到字段类型
					Method method=null;
					if("java.util.Date".equals(fieldType)) {
						//将java.util.Date转换成java.sql,Date
						method = cla.getDeclaredMethod(methodName, Class.forName("java.sql.Date"));//拿到方法对象
					}else {
						method = cla.getDeclaredMethod(methodName, Class.forName(fieldType));//拿到方法对象
					}
					method.setAccessible(true);//设置方法可访问,防止方法访问修饰符号位private
					method.invoke(newInstance, rs.getObject(columnName));//调用setter方法,执行对象属性赋值
				}
				list.add(newInstance);//将对象加入集合
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//关流
			try {
				if(rs!=null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(ps!=null)
					ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(con!=null)
					con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;	//返回list对象	
	}
	
}

测试类

package com.imooc.test;

import java.util.List;

public class TestDML_DQL {

	public static void main(String[] args) {		
		select();//查询
		change();//增删改
	}
	
	    /*
	 * 测试查询
	 */
	private static void select() {
		String sql="select * from t_student where sid=? or sid=?";//SQL语句
		Student student=new Student();	
		List<Student> list=DQLUtil.executeDQL(sql, student,1,2);//传参并得到返回的List集合,查询第一二条数据
		System.out.println("学生编号\t学生姓名\t生日\t性别");//输出结果
		for(Student stu:list) {
			System.out.println(stu.getSid()+"\t"+stu.getSname()+"\t"+stu.getSage()+"\t"+stu.getSsex());
		}
		
	}
    /*
	 * 测试修改
	 */
	private static void change() {
		String sql="update t_student set sname=? where sid=?";//SQL语句
		//调用方法,接收返回值
		boolean boo = DMLUtil.executeDML(sql, "宇宙第一大帅哥",1);
		System.out.println(boo);//输出执行结果	
	}

}

猜你喜欢

转载自blog.csdn.net/pengzonglu7292/article/details/86625415