反射封装工具类----零SQL插入(实用版)
V_1.0 需求:开发一个工具方法,辅助初级程序员在不需要掌握sql命令和JDBC的情况下,实现对数据库的插入操作。
V_4.0 实现0sql插入操作需要解决的问题.
1. 如何确认当前【陌生对象】关联的【表名】
2. 如何确认当前表中需要添加数据的字段
3. 如何将对象中数据和表中字段做一个一一对应
V_5.0 解决方案:
【实体类映射文件】描述某一个实体类与表的对象关系。
通过这个文件了解当前类关联的【表名称】
通过这个文件了解当前【表】和当前【对象】的字段和属性对应关系
工具类实现: public class ReflectUtil { /** * 功能: 0sql插入 * 步骤: * 1.将【实体类映射文件】加载到内存中。 2.定位【陌生对象】隶属的【类文件】 3.拼接sql第一部分 insert into [表名] 3.1 xPath="//@table" 3.2 从【实体类映射文件】获得表名 3.3. 拼接拼接sql第一部分 【insert into dept】 4.拼接sql第二部分 insert into [表名] (字段名1,字段名2) 4.1 从【实体类映射文件】自上而下获得所有的【property标签】 4.2 循环遍历每一个【property标签】 4.2.1 从【property标签】获得【colName属性内容】,从而获得【字段名】 4.2.2 将【字段名】拼接到sql命令----------insert into dept(DEPTNO,DNAME, LOC) 5.拼接sql第三部分 insert into [表名] (字段名1,字段名2) values(内容1,内容2); 5.1 循环遍历每一个【property标签】 5.1.1 每次循环获得一个【property标签】,依次读取【colType】获 得字段数据类型名,【name】 获得与当前字段对应的属性名 5.1.2 到【实体类】定位同名的【属性对象】 departId ==== private int departId 5.1.3 强制要求JVM,读取当前【实例对象】中指定【属性】的内容 属性对象.get(实例对象) Object value=obj.departId 5.1.4 根据当前【属性对象】对应的【字段的数据类型名称】,来决定读取数据在拼接到sql命令时,是否需要添加'' 6. 在不考虑JDBC开发流程的情况下,将拼接而成的sql命令输送到数据库中 ps.executeUpdate(sql) * * @param obj * @param xmlPath * @throws Exception */ public static void save(Object obj,String xmlPath,PreparedStatement ps)throws Exception{ //1.将【实体类映射文件】加载到内存中。 InputStream in = new FileInputStream(xmlPath); SAXReader readerObj = new SAXReader(); Document xmlObj=readerObj.read(in); // 2.定位【陌生对象】隶属的【类文件】 Class classObj= obj.getClass(); //3.拼接sql第一部分 insert into [表名] StringBuffer sql = new StringBuffer(); sql.append(" insert into "); //3.1 xPath="//@table" String xPath="//@table"; //3.2 从【实体类映射文件】获得表名 Attribute attrObj=(Attribute) xmlObj.selectSingleNode(xPath); String tableName = attrObj.getValue(); //dept //3.3. 拼接拼接sql第一部分 【insert into dept】 sql.append(tableName); //4.拼接sql第二部分 insert into [表名] (字段名1,字段名2) //4.1 从【实体类映射文件】自上而下获得所有的【property标签】 xPath="//property"; List<Element> propertyList=xmlObj.selectNodes(xPath); //4.2 循环遍历每一个【property标签】 int num =1; sql.append(" ("); for(Element proElement:propertyList){ //4.2.1 从【property标签】获得【colName属性内容】,从而获得【字段名】 String colName= proElement.attributeValue("colName"); //4.2.2 将【字段名】拼接到sql命令 sql.append(colName); if(num<propertyList.size()){ sql.append(","); num++; } } sql.append(") "); //5.拼接sql第三部分 insert into [表名] (字段名1,字段名2) values(内容1,内容2); // 5.1 循环遍历每一个【property标签】 num =1; sql.append(" values("); for(Element proElement:propertyList){ // 5.1.1 每次循环获得一个【property标签】,依次读取【colType】获得字段数据类型名,【name】 获得与当前字段对应的属性名 String colType = proElement.attributeValue("colType"); String fieldName = proElement.attributeValue("name"); // 5.1.2 到【实体类】定位同名的【属性对象】 departId ==== private int departId Field fieldObj=classObj.getDeclaredField(fieldName); fieldObj.setAccessible(true); //5.1.3 强制要求JVM,读取当前【实例对象】中指定【属性】的内容 Object value=fieldObj.get(obj); //5.1.4 根据当前【属性对象】对应的【字段的数据类型名称】,来决定读取数据在拼接到sql命令时,是否需要添加'' if("int".equals(colType) || "double".equals(colType)){ sql.append(value); }else if("char".equals(colType) || "varchar".equals(colType)){ sql.append("'"); sql.append(value); sql.append("'"); }else if("date".equals(colType)){ // mysql,允许将一个用字符串描述的数据,直接赋值给Date Date date =(Date)value; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); sql.append("'"); sql.append(sdf.format(date)); sql.append("'"); } if(num<propertyList.size()){ sql.append(","); num++; } } sql.append(")"); //输出拼接而成的sql System.out.println(sql.toString()); // 在不考虑JDBC开发流程的情况下,将拼接而成的sql命令输送到数据库中 ps.executeUpdate(sql.toString()); } } 表和实体类映射文件: <?xml version="1.0" encoding="UTF-8"?> <beans> <bean classPath="com.xiehe.entily.DeptVO" table="dept"> <property name="deptNo" type="int" colName="DEPTNO" colType ="int"></property> <property name="dName" type="java.lang.String" colName="DNAME" colType="varchar"></property> <property name="loc" type="java.lang.String" colName="LOC" colType="varchar"></property> </bean> </beans>