人事管理系统项目(四)
在开始写后端功能前先来配置好数据库的连接,我在这建了一个utils包,下面单独写一个DBUtil类,这个类里面封装了传统的连接数据库的方法以及数据库连接池技术还有一些操作数据库的方法等等,现在来看看代码:
package com.jiazhong.hr.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.beanutils.ConvertUtils;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/***
* 数据库操作辅助类
* 该类中封装了关于数据库的常用操作
*/
public abstract class DBUtil {
protected Connection conn = null;
protected PreparedStatement ps = null;
protected ResultSet rs = null;
//创建数据源DataSource对象,基于Druid的数据源
private static DataSource dataSource;
/***
* 静态代码块
* 当类加载时就被执行,而且只会执行一次
*/
static {
try {
//读取db.properties文件中的数据
InputStream input = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
//InputStream input = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
//Properties类,该类的一个实例对应一个properties文件
//Properties类是一个Map集合
Properties properties = new Properties();
//将输入流中的数据加载到properties对象
properties.load(input);
//创建Druid的dataSource对象
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/***
* 获得连接对象的方法
* @return Connection 连接对象
*/
protected Connection getConn1() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hr-project-web?useSSL=false", "root", "root");
return conn;
}
/***
* 使用Druid数据库连接池技术连接数据库
* @return
* @throws ClassNotFoundException
* @throws SQLException
*/
/*protected Connection getConn2() throws ClassNotFoundException, SQLException {
//设置数据源的连接属性
//设置数据库驱动
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//设置连接字符串
dataSource.setUrl("jdbc:mysql://localhost:3306/hr-project-web?useSSL=false");
//设置数据库登录用户名和密码
dataSource.setUsername("root");
dataSource.setPassword("root");
*//**设置数据库连接池相关属性**//*
//设置连接池中连接对象的初始数量
dataSource.setInitialSize(5);
//设置最小空闲连接数
dataSource.setMinIdle(3);
//最大活动连接数
dataSource.setMaxActive(10);
//最大等待时间(毫秒)
dataSource.setMaxWait(1000);
//通过连接池获得连接对象
conn = dataSource.getConnection();
return conn;
}*/
/***
* 使用Druid数据库连接池技术连接数据库
* @return
* @throws ClassNotFoundException
* @throws SQLException
*/
protected Connection getConn()throws ClassNotFoundException, SQLException {
//从连接池中获取一个连接对象
conn = dataSource.getConnection();
return conn;
}
/***
* 释放数据库资源方法
*/
protected void closeAll(){
try {
if(rs != null){
rs.close();
}
if(ps != null){
ps.close();
}
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
conn = null;
ps = null;
rs = null;
}
}
/***
* 执行增、删、改等修改数据库的操作
* @param sql 带有?号占位符的SQL语句
* @param params SQL语句中?号占位符的值
* 由于SQL语句中可以有多个?号也可以没有?号,
* ?号所占位的数据的数据类型也是不统一的
* 所以该参数为一个Object数组
* @return int类型整数,该返回值表示SQL语句执行后的影响行数
*/
protected int executeUpdate(String sql,Object... params){
try {
//1.连接数据库(调用本类中的连接数据库方法获得数据库连接对象)
this.getConn();
//2.获得预处理对象(根据连接对象和SQL语句创建预处理对象)
ps = conn.prepareStatement(sql);
//3.设置SQL语句中?号占位符的值
//3.1判断SQL语句中是否存在?号占位符
// (根据params数组对象判断,该对象存在并且长度大于0表示有?号占位符)
if(params != null && params.length != 0){
//3.2 SQL语句中存在?号占位符,则循环为每个?号占位符赋值
for(int i=0;i<params.length;i++){
//通过ps.setObject()方法为不同类型的?号占位符赋值
ps.setObject(i+1,params[i]);
}
}
//4.执行SQL语句并返回结果
return ps.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源(调用本类中释放资源方法)
this.closeAll();
}
return 0;
}
/***
* Object... params:可变参数,该位置的参数数量是可变的,可以为0个也可以为多个
* 在方法声明时可变参数必须在所有参数的最后
* 可变参数是数组
*/
/**
* 通用查询(针对单表的通用查询)
* @param sql SQL语句
* @param cla SQL语句中查询的表所对应的实体Bean的类的Class对象
* @param params SQL语句中?号占位符的值
* @return List集合
*/
protected <T> List<T> executeQuery(String sql, Class<T> cla, Object... params){
try {
//1.连接数据库(调用本类中的连接数据库方法获得数据库连接对象)
this.getConn();
//2.获得预处理对象(根据连接对象和SQL语句创建预处理对象)
ps = conn.prepareStatement(sql);
//3.设置SQL语句中?号占位符的值
//3.1判断SQL语句中是否存在?号占位符
// (根据params数组对象判断,该对象存在并且长度大于0表示有?号占位符)
if(params != null && params.length != 0){
//3.2 SQL语句中存在?号占位符,则循环为每个?号占位符赋值
for(int i=0;i<params.length;i++){
//通过ps.setObject()方法为不同类型的?号占位符赋值
ps.setObject(i+1,params[i]);
}
}
//4.执行查询SQL语句,返回结果集
rs = ps.executeQuery();
//从结果集中获得结果集的"元数据"(元数据指:当前结果集的表结构)
ResultSetMetaData rsmt = rs.getMetaData();
//获得结果集中记录的总列数
int columnCount = rsmt.getColumnCount();
//创建用于存储结果对象的List集合
List<T> list = new ArrayList<>();
while(rs.next()){
//创建类的对象cla
T t = cla.newInstance();
//循环列
for(int i=0;i<columnCount;i++){
//构建与对象中属性相对应的set方法
//获得set方法名
//获得set方法所对应的属性名(属性名和表中的列名一致)
String fieldName = rsmt.getColumnName(i+1);
//根据属性名拼接方法名
String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
//获得set方法参数的类型
//根据属性名获得属性对象
Field field = cla.getDeclaredField(fieldName);
//创建set方法所对应的method对象
Method method = cla.getDeclaredMethod(methodName,field.getType());
//根据列编号获得该列编号对应的数据
Object value = rs.getObject(i+1);
//调用method方法并为t对象赋值
//使用ConvertUtils对value数据进行类型转换,转换为Java中属性所对应的类型
method.invoke(t, ConvertUtils.convert(value,field.getType()));
}
//将t对象添加到list集合中
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
this.closeAll();
}
return null;
}
}
在resources下建一个db.properties文件,在这里配置数据库连接属性和连接池的属性;这样,数据库连接就配置好了。