注:这里使用mysql数据库。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=1234
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 使用JDBC进行数据库连接与关闭的工具类
*
* @author XIAOHU
* @since 2018-04-08
*/
public class JDBCUtil {
private static String driver;
private static String url;
private static String username;
private static String password;
static {
init();
try {
// 加载一次驱动
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 初始化数据库连接数据
*/
public static void init() {
Properties prop = new Properties();
InputStream is =
JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driver = prop.getProperty("jdbc.driver");
url = prop.getProperty("jdbc.url");
username = prop.getProperty("jdbc.username");
password = prop.getProperty("jdbc.password");
}
/**
* 获取数据库连接
*
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 释放所有资源
*
* @param rs
* 结果集
* @param st
* Statement对象
* @param conn
* 数据库连接
*/
public static void closeAll(ResultSet rs, Statement st, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 字符串处理工具类
*
* @author XIAOHU
* @since 2018-04-11
*/
public class StringUtil {
/**
* 将字符串首字母转为大写
* @param str 要转换的字符串
* @return 返回转换后的首字母大写的字符串
*/
public static String toUpper(String str){
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
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 cn.xiyou.petshopsystem.utils.JDBCUtil;
import cn.xiyou.petshopsystem.utils.StringUtil;
/**
* 封装JDBC的增删改查功能
*
* @author XIAOHU
* @since 2018-04-11
*
*/
public class BaseDao<T> {
/**
* 封装增、删、改功能
*
* @param sql
* 需要执行的sql语句
* @param args
* 不定参数,是对sql语句中的占位符“?”传入的参数
* @return 返回操作所影响的行数
*/
public int executeUpdate(String sql, Object... args) {
Connection conn = null;
PreparedStatement pst = null;
int rows = 0;
try {
conn = JDBCUtil.getConnection();
pst = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pst.setObject(i + 1, args[i]);
}
rows = pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.closeAll(null, pst, conn);
}
return rows;
}
/**
* 查询一条记录
*
* @param sql
* 需要执行的sql语句
* @param cls
* 由此 Class对象建模的类的类型。如果将被建模的类未知,则使用 Class>。
* 例如,String.class 的类型是Class。
* @param args
* 不定参数,是对sql语句中的占位符“?”传入的参数
* @return 返回操作所影响的行数
*/
public T selectOne(String sql, Class cls, Object... args) {
List list = this.selectMany(sql, cls, args);
return list.isEmpty() ? null : list.get(0);
}
/**
* 查询所有记录
*
* @param sql
* 需要执行的sql语句
* @param cls
* 由此 Class对象建模的类的类型。如果将被建模的类未知,则使用 Class>。
* 例如,String.class 的类型是Class。
* @param args
* 不定参数,是对sql语句中的占位符“?”传入的参数
* @return 返回操作所影响的行数
*/
public List selectMany(String sql, Class cls, Object... args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
List list = new ArrayList();
try {
conn = JDBCUtil.getConnection();
pst = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pst.setObject(i + 1, args[i]);
}
rs = pst.executeQuery();
//从结果集中获取数据库表的相关信息
ResultSetMetaData metaData = rs.getMetaData();
while (rs.next()) {
T obj = cls.newInstance();// 创建cls实例
//metaData.getColumnCount():获得数据库表中列数(字段数)
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);//获取字段名
// 动态拼接成该属性对应实体中的setter方法的方法名(=set字符串拼接首字母大写
// 的属性名)。如:setName(Stringname)的方法名为setName
String name = "set" + StringUtil.toUpper(columnLabel);
// 获取实体中所有声明(私有+公有)的属性
Field field = cls.getDeclaredField(columnLabel);
// 获取实体中所有声明(私有+公有)的形参为field.getType()类型,方法名为
// name的方法
Method method = cls.getDeclaredMethod(name, field.getType());
// 通过结果集获取字段名为fieldName(与实体中的对应属性名完全相同)的值
Object realParam = rs.getObject(columnLabel);
// 执行obj对象中的method方法,传入的实参为realParam
method.invoke(obj, realParam);
}
list.add(obj);
}
} catch (SQLException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} finally {
JDBCUtil.closeAll(null, pst, conn);
}
return list;
}
/**
* 查询总记录数
*
* @param sql
* 需要执行的sql语句
* @param args
* 需要对sql语句中的占位符“?”传入的参数数组
* @return 返回操作所影响的行数
*/
public int selectCount(String sql, Object... args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
int count = 0;
try {
conn = JDBCUtil.getConnection();
pst = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pst.setObject(i + 1, args[i]);
}
rs = pst.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.closeAll(null, pst, conn);
}
return count;
}
}
说明:这里仅做了部分封装,更多的封装需要自己去实现。BaseDao.java中的封装代码为重点,类似于一些框架底层的实现,想要更深一步学习封装的,希望自己去看一些框架源码和设计模式。