本文前置内容:JAVA & 数据库编程 & ORM工具(上)
文件如图 注意url的书写,其中school是我用的数据库名。
其实无论是增删改查,都是按照一定的步骤来的。
第一步,获取映射关系类第二步,构建基本的sql语句结构第三步,通过模板类,完善sql语句第四步,执行操作,处理返回结果这里面的一个需要注意的地方:由于模板类的成员是private保护,无法直接对其进行操作。 而使用field.setAccessible(true);会破坏其保护。但有趣的是,我们拥有set,get函数。而且其一般规则是 set方法 : set + 成员名(首字母大写)(成员类型){} get方法:get + 成员名(首字母大写)(){} 所以我们可以通过**使用反射获取方法,来实现对成员的读写。
具体get
private Object getFieldValue(Class<?> kClass, Field field, Object object) { String fieldName = field.getName(); //注意,由于成员是private保护,不能直接获取,但是可通过get函数获得 String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); try { Method method = kClass.getDeclaredMethod(methodName); Object value = method.invoke(object, new Object[] {}); return value; } catch (Exception e) { e.printStackTrace(); return null; } }具体set
private void initObject(ClassTableDefinition ctd, Object result, ResultSet resultSet) { Class<?> modelKClass = result.getClass(); List<FieldCloumnDefinition> fdList = ctd.getfDefinitions(); for (FieldCloumnDefinition fd : fdList) { try { Object value = resultSet.getObject(fd.getCloumn()); System.out.println(value.getClass()); Field field = fd.getField(); String fieldName = field.getName(); //set String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method method = modelKClass.getDeclaredMethod(methodName, field.getType()); method.invoke(result, value); } catch (Exception e) { e.printStackTrace(); } } }熟悉增加操作:INSERT INTO 表名([字段名1,字段名2,字段名3])VALUES(‘值1’,‘值2’,‘值3’),(‘1值1’,‘1值2’,‘1值3’)…
/** * 从一个类中将一条完整的记录存储到数据库中。 * @param object */ public void save(Object object) { //第一步,获取映射关系类 Class<?> kClass = object.getClass(); ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass); if (ctd == null) { System.out.println("类[" + kClass.getName() + "]没有映射关系!"); } StringBuffer sql = new StringBuffer(); //第二步,构建基本的sql语句结构 sql.append("INSERT INTO ").append(ctd.getTableName()) .append(" (").append(ctd.getCloumnList()) .append(") VALUES("); for (int index = 0; index < ctd.getFieldCount(); index++) { sql.append(index == 0 ? "" : ",").append("?"); } sql.append(");"); PreparedStatement statement; try { statement = connection.prepareStatement(sql.toString()); //第三步,通过模板类,完善sql语句 //INSERT INTO student (student.id,student.name,student.age) VALUES(?,?,?); 上面获得sql语句 //接下来需要将?,一一修改成存储在模板类的数据 prepareStatment(ctd, statement, object); //第四步,执行操作 statement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } private void prepareStatment(ClassTableDefinition ctd, PreparedStatement statement, Object object) { Class<?> kClass = object.getClass(); List<FieldCloumnDefinition> fdList = ctd.getfDefinitions(); int index = 0; for (FieldCloumnDefinition fd : fdList) { Field field = fd.getField(); //获取到每个成员的值,完成sql语言 Object value = getFieldValue(kClass, field, object); try { System.out.println(value); statement.setObject(index + 1, value); } catch (SQLException e) { e.printStackTrace(); } index++; } }熟悉删除操作:语法: DELETE FROM 表名 [WHERE 条件]
/** * 通过主键值,删除某一条记录 * @param kClass * @param id */ public void delete(Class<?> kClass,Object id) { ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass); if (ctd == null) { System.out.println("类[" + kClass.getName() + "]没有映射关系!"); return; } StringBuffer sql = new StringBuffer(); sql.append("DELETE ").append("FROM ").append(ctd.getTableName()) .append(" WHERE ").append(ctd.getPrimaryKey().getCloumn()) .append("=?;"); //DELETE FROM student WHERE id=?; try { PreparedStatement statement = connection.prepareStatement(sql.toString()); statement.setObject(1, id); statement.execute(); } catch (SQLException e) { e.printStackTrace(); } }熟悉修改操作:UPDATE 表名 SET colnum_name = value,[colnum_name = value, …] where [条件]
/** * 修改一个记录 * @param object */ public void update(Object object) { Class<?> kClass = object.getClass(); ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass); //第一步 if (ctd == null) { System.out.println("类[" + kClass.getName() + "]没有映射关系!"); } StringBuffer sql = new StringBuffer(); sql.append("UPDATE ").append(ctd.getTableName()) .append(" SET"); List<FieldCloumnDefinition> fList = ctd.getfDefinitions(); boolean isFirst = true; for (FieldCloumnDefinition fcd : fList) { if (fcd.equals(ctd.getPrimaryKey())) { continue; } String cloumnName = fcd.getCloumn(); sql.append(isFirst ? " ": ",").append(cloumnName) .append("=?"); isFirst = false; } sql.append(" WHERE ").append(ctd.getPrimaryKey().getCloumn()).append("=?;"); //第二步完成 //UPDATE student SET name=?,age=? WHERE id=?; try { PreparedStatement statement = connection.prepareStatement(sql.toString()); int index = 0; for (FieldCloumnDefinition fd : fList) { if (fd.equals(ctd.getPrimaryKey())) { continue; } //第三步关键 Object value = getFieldValue(kClass, fd.getField(), object); statement.setObject(++index, value); } Object idValue = getFieldValue(kClass, ctd.getPrimaryKey().getField(), object);//get statement.setObject(++index, idValue); //第四步执行 statement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } }查目前提供两种,查一条匹配记录,和查表中所有记录。 查一条:SELECT 字段名, 字段名… FROM 表名 WHERE[条件]
/** * 根据某一条件,查询一条完整的记录 * @param <T> * @param kClass SELECT查询结果生成的对象 * @param id WHERE 使用的主键条件 * @return */ @SuppressWarnings("unchecked") public <T>T get(Class<?> kClass, Object id){ //第一步 ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass); if (ctd == null) { System.out.println("类[" + kClass.getName() + "]没有映射关系!"); return null; } //生成查询语句,第二步 StringBuffer sql = new StringBuffer(); sql.append("SELECT ").append(ctd.getCloumnList()) .append(" FROM ").append(ctd.getTableName()) .append(" WHERE ").append(ctd.getPrimaryKey().getCloumn()).append("=?;"); //SELECT student.id,student.name,student.age FROM student WHERE id=?; Object result = null; try { PreparedStatement statement = connection.prepareStatement(sql.toString()); statement.setObject(1, id);//第三步简单 ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { result = newInstance(ctd, resultSet);//将数据保存到模板类中 } } catch (Exception e) { e.printStackTrace(); } return (T) result; } private Object newInstance(ClassTableDefinition ctd, ResultSet resultSet) throws InstantiationException, IllegalAccessException { Class<?> kClass = ctd.getModelClass(); Object result = kClass.newInstance(); initObject(ctd, result, resultSet);//set return result; }查询所有记录SELECT * FROM student
/** * 获得表中所有数据 * @param <T> * @param kClass * @return */ @SuppressWarnings("unchecked") public <T> List<T> list(Class<?> kClass){ ClassTableDefinition ctd = ClassTableFactory.getCTD(kClass); if (ctd == null) { System.out.println("类[" + kClass.getName() + "]没有映射关系!"); return null; } StringBuffer sql = new StringBuffer(); sql.append("SELECT ").append("* ") .append("FROM ").append(ctd.getTableName()); //SELECT * FROM student List<T> result = new ArrayList<T>(); try { PreparedStatement statement = connection.prepareStatement(sql.toString()); ResultSet rs = statement.executeQuery(); while (rs.next()) { T element = (T) newInstance(ctd, rs); result.add(element); } } catch (Exception e) { e.printStackTrace(); } return result; }其实虽然完成了增删改查,但还是又不少地方有待完善。比如说排序,比如查询指定记录的少数列数据。
因为上述操作都是针对一条完整记录。不过从整体而言,只要规范好sql语句的搭建,就能实现基本功能。所以称之为工具不为过。当然,工具也是越用越好用。(不断完善)
笔者水平有限,目前只能描述以上问题,如果有其他情况,可以留言,有错误,请指教,有继续优化的,请分享,谢谢! 本篇文章是否有所收获?阅读是否舒服?又什么改进建议?希望可以给我留言或私信,您的的分享,就是我的进步。谢谢。
2020.10.24 网安院2楼