配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/project
jdbc.user=root
jdbc.password=123456
jdbc.datasource.size=10
常量接口
package com.lirong.sparkproject.constant;
public interface Constants {
/**
* 数据库相关常量
*/
String JDBC_DRIVER = "jdbc.driver";
String JDBC_URL = "jdbc.url";
String JDBC_USER = "jdbc.user";
String JDBC_PASSWORD = "jdbc.password";
String JDBC_DATASOURCE_SIZE="jdbc.datasource.size";
}
JDBC工具类
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;
import com.lirong.sparkproject.constant.Constants;
public abstract class JDBCHelper {
//配置对象
private static Properties prop=new Properties();
/*
* jdbc变量
*/
static String driver=null;
static String url=null;
static String user=null;
static String password=null;
//thread封装Connection对象
static ThreadLocal<Connection> thread=new ThreadLocal<Connection>();
//唯一空构造器私有化,不允许外部创建对象
private JDBCHelper() {}
/**
* 静态代码块为jdbc变量赋值
* 因为静态代码块最先执行,所以调用getConnection()方法时,
* 该方法内部的jdbc变量就完成了赋值操作
*/
static {
try {
//动态获取配置文件的路径
InputStream in=JDBCHelper.class.getClassLoader().getResourceAsStream("my.properties");
prop.load(in);//加载键值对信息
/*
* Constants常量接口中保存了很多常量,这些常量的值就是配置文件k-v数据的键
*
*/
driver=prop.getProperty(Constants.JDBC_DRIVER);
url=prop.getProperty(Constants.JDBC_URL);
user=prop.getProperty(Constants.JDBC_USER);
password=prop.getProperty(Constants.JDBC_PASSWORD);
/*
* 加载驱动,静态代码块只执行一次,驱动只加载一次(加载驱动很耗性能的)
*/
Class.forName(driver);//加载驱动
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过本方法客获取一个MySQL数据库的Connection对象
*
* @return Connection对象
*/
public static Connection getConnection() {
Connection con = thread.get();
if(con==null) {
try {
con = DriverManager.getConnection(url, user, password);
thread.set(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
return con;//返回jdbc连接
}
/**
* 本方法中调用Date类型变量的setter方法时使用的是java.sql.Date,
* 所以实体类在声明Date类型变量时一定声明成java.sql.Date
* 至少Date类型变量对应的setter方法的形参必须是java.sql.Date,否则报错
*
* 查询完毕后,使用者通过JDBCHelper.getConnection()获取连接对象,并关闭它
* 外部获取的连接对象与本方法使用的连接对象,在同一线程类,是同一个对象
*
* @param sql 要执行的查询语句
* @param t 实体类对象
* @param objs SQL语句中的参数
* @return 装有实体类对象的list集合
*/
public static <T> List<T> executeQuery(String sql,T t,Object...objs){
//声明jdbc变量
List<T> list=new ArrayList<>();
Connection conn = null;
PreparedStatement ps =null;
ResultSet rs =null;
try {
conn = JDBCHelper.getConnection();
ps = conn.prepareStatement(sql);
//给占位符赋值
if(objs!=null) {
for(int i=0;i<objs.length;i++) {
ps.setObject((i+1), objs[i]);
}
}
//执行sql语句
rs = ps.executeQuery();
//获取结果集中字段的所有信息
ResultSetMetaData rm = rs.getMetaData();
int columnCount = rm.getColumnCount();//获取字段数
//遍历结果集
while(rs.next()) {
Class<? extends Object> cla = t.getClass();//获取类对象
T newInstance=(T)cla.newInstance();//获取类的对象
//一个for循环封装一条记录的所有值
for(int i=1;i<=columnCount;i++) {
String columnName = rm.getColumnName(i);//获取字段名
//获取字段对应的setter方法
String methodName="set"+columnName.substring(0, 1).toUpperCase()+columnName.substring(1);
String columnClassName = rm.getColumnClassName(i);//获取字段java类型的完全限定名
//创建方法对象
Method method = cla.getDeclaredMethod(methodName, Class.forName(columnClassName));
method.invoke(newInstance,rs.getObject(columnName));//调用setter方法,执行对象属性赋值
}
list.add(newInstance);//将对象加入集合
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//关流
JDBCHelper.close(ps,rs);
}
return list;
}
/**
* 该方法封装了MySQL数据库的DML操作
* 如果要实现事务:
* 事务的开启,关闭,回滚,及连接对象的关闭等操作
* 使用者通过JDBCHelper.getConnection()获取连接对象,通过连接对象并在外部声明
* 外部获取的连接对象与本方法使用的连接对象,在同一线程类,是同一个对象
*
* @param sql 要执行的SQL语句
* @param objs SQL语句中的参数
* @return 成功执行返回影响的记录条数,否则返回0
* @throws SQLException
*/
public static Integer executeDML(String sql,Object...objs) {
//声明jdbc变量
Connection conn =null;
PreparedStatement ps =null;
Integer i =0;
try{
conn = JDBCHelper.getConnection();
ps = conn.prepareStatement(sql);
//给占位符赋值
if(objs!=null) {
for(int j=0;j<objs.length;j++) {
ps.setObject((j+1), objs[j]);
}
}
//执行SQL语句
i = ps.executeUpdate();
}catch(SQLException e) {
e.printStackTrace();
}finally {
//关流
JDBCHelper.close(ps);
}
return i;
}
/**
* 关流的方法,接收任意多个任意类型的流对象
* 如果关闭的流对象有关闭的先后顺序
* 请将要先关闭的流对象放在前方
*
* 所有流对象的顶级父接口都是AutoCloseable
* @param t 要关闭的流对象,可以是一个或多个(也可以是零个)
*
*/
private static <T>void close(T...t){
//循环关流
for(T tmp:t) {
//关闭流对象
if(tmp instanceof AutoCloseable) {
try {
((AutoCloseable)tmp).close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}