前面介绍了连接数据库的工具类,现在就可以使用这些工具类连接数据
库,并编写相应的代码进行对数据库的增删改查了。出于同样的道理,为了更方便,安全,可移植性更强。下面介绍通用的增删改查实现。增删改操作一个方法就可以实现,查询操作单独作为一个方法,是因为增删改都不返回具体的数据库里面的数据,而查询操作返回具体的数据。
预备知识
首先,我们要使用上一篇的 JDBC_Utils 工具类,以及针对数据库中的不同的表,编写对应的 javabean 类。
通用的增删改操作
// 通用的增删改 public void update(String sql, Object ...args) {// sql语句中占位符的个数等于可变形参的个数 Connection conn = null; PreparedStatement ps = null; try { // 1.获取连接 conn = JDBC_Utils.getConnection(); // 2.预编译 ps = conn.prepareStatement(sql); // 3.填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i+1, args[i]); } // 4.执行 ps.execute(); } catch (Exception e) { e.printStackTrace(); } finally { //关闭资源 JDBC_Utils.closeResource(conn,ps); } }
复制代码
下面测试增删改操作,了解是如何使用上面的方法的。
@Test public void testCustomUpdate(){ // 测试删除 // ?表示占位符,和prepareStatement(sql)搭配可以有效防止SQL注入,出现安全问题// String sql = "delete from customers where id = ?"; // update(sql, 3); // 对test数据库中的order表进行处理 String sql = "update `order` set order_name = ? where order_id = ?"; update(sql,"DD", 2); }
复制代码
通用的查询操作
注意:本方法使用了泛型:
原因:该方法是通用的查询方法,可以对数据库中不同的表进行查询,但是方法的返回值类型不确定到底是哪种类型,因此使用泛型可以解决这个问题。
本方法还使用了反射:
原因:
在 new 一个对应的对象时对查询的数据进行封装时,不知道到底该使用哪个 javabean 类,因此,使用反射可以解决这个问题,由方法传入的第一个参数,在方法体内部可以确定该 new 哪个对象。代码中的 24 行程序就是体现。
关于别名:数据库中的表的字段不一定是和 javabean 中的类的属性完全相同,通过在 sql 语句中设置把类的属性作为字段的别名,可以避免出现查询错误。
// 该方法可以得到多条数据,所用技术包括反射,泛型public <T> List<T> getForList(Class<T> clazz, String sql, Object ...args){
Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBC_Utils.getConnection(); ps = conn.prepareStatement(sql); // 填充占位符,目的是把sql语句填充完毕 for (int i = 0; i < args.length; i++) { ps.setObject(i+1, args[i]); }
// 获取结果集 rs = ps.executeQuery(); // 获取结果集的元数据:ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); // 通过ResultSetMetaData获取结果集中的列数,也就是数据库中的一条数据的字段个数 int columnCount = rsmd.getColumnCount(); // 创建集合对象 ArrayList<T> ts = new ArrayList<>(); while (rs.next()){ T t = clazz.newInstance();// 造一个对象 for (int i = 0; i < columnCount; i++) { Object columnValue = rs.getObject(i + 1); // 得到每一个字段对应的值,注意:这里你是不知道查了几个字段,以及字段的顺序 // 获取每个列的列名(也就是字段的字段名), //这里使用的是getColumnLabel()方法,如果sql语句给字段起了别名,返回的是别名,如果没有起别名,返回的就是真实的字段名 String columnName = rsmd.getColumnLabel(i + 1); // 给cus对象指定的某个属性,赋值为value(给cust对象指定的columnName属性,赋值为columnValue),通过反射 Field declaredField = clazz.getDeclaredField(columnName); declaredField.setAccessible(true); declaredField.set(t, columnValue); } ts.add(t); } return ts; } catch (Exception e) { e.printStackTrace(); } finally {
JDBC_Utils.closeResource(conn,ps,rs); } return null; }
复制代码
通用查询操作测试,了解如何使用该方法
@Test public void testGetForList(){ // 该例子没有别名,因为javabean类的属性和字段名一样,这个地方具体问题具体分析 String sql = "select id, name, email from customers where id < ?"; List<Customer> forList = getForList(Customer.class, sql, 5); forList.forEach(System.out::println); }
复制代码
评论