暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

第6讲:通用查询

何先振 2024-03-14
228

以下文章来源于何先振,责编小何


单个表的通用查询



上讲我们讲了PreparedStatement接口的使用,学会了如何进行增删改查,根据增删改的特点封装了一个通用的增删改操作方法。


那么查询我们是否也可以进行封装成通用的呢?


下面我们就来进行封装成通用的查询。


上篇中在查询用户信息时,我们发现所有的查询SQL语句不一样,设置参数也不同,获取结果集的参数也不一样。





参照通用的增删改的方式,我们可以把SQL和SQL的参数值作为参数提取出来。





获取查询结果集时,不同的查询SQL,有多少列我们现在还是自己去识别的。


比如:这里我知道一行数据有4列,所以写四个get方法接收。





要想获取列的数量,我们查看JDK的开发文档,ResultSet提供了getMetaData方法让我们获取。





我们调用这个方法,会返回一个ResultSetMetaData对象。





查看ResultSetMetaData对象的方法。找到了一个可以获取列数量的方法。





调用此方法,获取列的数量。





有了列的数量,我们就可以遍历得到列的索引,进行循环获取每列的值。





拿到值,我们如何将值添加到对象user中去呢?


之前我们是通过set方法设置进去的,但是现在我们不知道要调用哪个set方法。





除了直接调用对象的属性set方法,我们还可以通过反射调用set方法。


首先获取User类的Class对象。





要想调用属性的set方法,需要通过Class对象拿到对应的属性对象。这个时候就需要提供属性名。


为了解决属性名的问题。我们写SQL的时候可以通过表的字段名来充当属性名。


但是大多数情况下,字段名和属性名是不一样的,这个时候我们可以给字段名起别名,这样来保持字段名和属性名一样。


这样我们只需要获取列名就可以了,竟然能够获取列的数量,肯定还可以让我们获取列名。查JDK的开发文档。


我们看到ResultMetaData对象,还提供了获取列名和列的别名方法。





由于字段名和属性名不一样时,要起别名,所以我们不能直接调用获取列名的方法,要调用获取别名的方法。这个方法说明,没有起别名就返回列名。





调用这个方法就得到了列名。





然后就可以通过反射进行调用set方法了。





查的数据可能会有多个,我们可以添加List中,返回List中的User对象。





使用完之后别忘了,结果集也需要关闭资源。








准备SQL语句,运行程序,成功查出了对象。

注意:这里的SQL语句中的字段名跟属性名不一样,需要取别名作为属性名。





通用表的通用查询



上面的通用查询方法还有个缺陷,就是只能查单个表。因为方法中写死了。是创建User对象,而User对象就表示user表。





接下来我们接着优化,将这段代码如何变成动态的呢?


针对不同类的对象,我们可以使用范型来实现。


首先将方法改写成泛型方法,不同的类传入不同类的Class对象。





将集合修改为泛型集合,用来装泛型对象。去掉直接new具体的用户对象,使用class对象通过反射创建泛型对象。





调用通用查询方法,需要增加传入对应类的Class对象,获取查询数据。一个通用的查询方法就被我们封装成了。





解决SQL注入问题



Statement接口有SQL注入的安全问题,那么使用PreparedStatement可以解决这种注入问题嘛?


打开到Statement接口注入SQL的代码。





我们改成使用PreparedStatement接口





修改之后运行程序,无法查出数据。





这是因为创建PreparedStatement时已经提前将SQL给它了,结构已经固定下来了,不能再修改成or的关系。


使用PreparedStatement的好处,除了可以解决SQL注入的安全问题。


还可以操作blob类型的数据,这是Statement做不到的。在做批量操作时会比Statement更高效。这些下篇将为大家来讲解。



扫码进微信答疑群




点击上方"何先振"关注并选择设为星标
各类IT技术文章不会错过!

文章转载自何先振,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论