由于我们不确定需要查找的表,以及需要创建的实体类,所以在参数处使用反射(Class<T> clazz),在调用时传入实体类的运行时类(实体类 . class),同时,相对于查询来讲,通常不会只有一个值,所以,我们需要在开始时创建一个List集合,后续将查询到的数据赋值给实体类的实例,然后将这些实例存入到集合中作为返回值返回,我们这样理解,每一行对应着实体类的一个对象,每个字段对应实体类的属性。
1. 填充完占位符以后执行预编译sql语句,注意,此时使用executeQuery()方法,此方法会有一个ResultSet类型的返回值(结果集),我们需要拿到这个结果集。
2. 在进行下一步之前,请允许我多说两句, 因为我们的查询是围绕列(字段)展开的,但是我们此时无法确定具体的字段数量,怎么办呢,调用刚刚获取到的结果集的getMetaDate获取到ResultSetMetaData类型的metaData,接着调用metaData的getColumnCount()方法获取到当前获取到的结果集的列(字段)数。
3. 使用while循环,将结果集的next()方法作为判断条件,next()方法在结果集有下一项时,会返回true,同时将指针下移。
4. 调用运行时类clazz的newInstance()方法创建一个运行时类的对象,此方法会调用运行时类的空参构造器,若没有空参构造器会抛出异常。
5. 调用结果集rs的getObject()方法获取到当前的value值,调用metaData的getColumnLabel()方法获取到当前的字段名,之所以用这个方法,是因为这个方法获取到的是通过查询获取到的列名,也就是说可以获取到别名。
6. 使用运行时类的getDeclaredField()方法获取到我们刚才查询的字段所对应属性值,接着使用set方法将刚刚获取到的value设置给对应的属性值,需要注意的时,在使用set方法之前,先调setAccessible(true)。
7. 此时数据已经赋值给实体类的实例,将实体类的实例添加到list中,循环结束后,将list作为返回值返回
8. 关闭资源,若程序执行过程中出现异常,返回null。