注: 这里使用mysql数据库。java
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<String>。 * @param args * 不定参数,是对sql语句中的占位符“?”传入的参数 * @return 返回操做所影响的行数 */ public T selectOne(String sql, Class<T> cls, Object... args) { List<T> list = this.selectMany(sql, cls, args); return list.isEmpty() ? null : list.get(0); } /** * 查询全部记录 * * @param sql * 须要执行的sql语句 * @param cls * 由此 Class对象建模的类的类型。若是将被建模的类未知,则使用 Class<?>。 * 例如,String.class 的类型是Class<String>。 * @param args * 不定参数,是对sql语句中的占位符“?”传入的参数 * @return 返回操做所影响的行数 */ public List<T> selectMany(String sql, Class<T> cls, Object... args) { Connection conn = null; PreparedStatement pst = null; ResultSet rs = null; List<T> list = new ArrayList<T>(); 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中的封装代码为重点,相似于一些框架底层的实现,想要更深一步学习封装的,但愿本身去看一些框架源码和设计模式。mysql