博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java——JDBC小结(4)
阅读量:5090 次
发布时间:2019-06-13

本文共 7193 字,大约阅读时间需要 23 分钟。

在前面的关于JDBC的叙述中,着重说明了工具类的创建办法,接下来我将就我之前没有提到的查询的方式加以说明,在说明查询之前我先引出一个新的概念就是结果集这个类,及他的相关的一些方法

1.结果集

之前有提到过发送SQL的Statement这个类,他的主要作用就是发送SQL到数据库,对于增,删,改,使用的方法是Statement.executeUpdata();注意他的返回值是一个整形,也就是返回的是数据库受影响的行数,而在进行查找的SQL时,要调用的方法是Statement.executeQuery();

这个方法将返回一个结果集,也就是说你要查询的结果将以集合的方式返还回来

以下是一段测试代码:

1     @Test 2     public void test1(){ 3         //假设传入的员工id是 4         int id=7369; 5         Connection con=null; 6         //创建连接 7         try { 8             String sql="select * from emp_jiawenzhe " 9                     + "where empno="+id;10             con=DBUtil.getConnection();11             Statement smt=con.createStatement();12             ResultSet rs=smt.executeQuery(sql);13             //结果集中封装了多行数据,需要遍历14             while(rs.next()){15                 //rs.get类型(字段名)16                 //rs.get类型(字段索引)17                 System.out.println(rs.getInt("empno"));18                 System.out.println(rs.getString("ename"));19             }20         } catch (SQLException e) {21             //记录日志22             e.printStackTrace();23             //能处理则自己处理,处理不了向上抛给调用者24             throw new RuntimeException("查询员工失败",e);25         }finally{26             //归还连接27             DBUtil.close(con);28         }29     }

根据SQL语句可以看出,是要从一张员工表里面找到在指定id的员工,rs是结果集的实例化,rs.next()方法就是去遍历每一个字段,当字段遍历到最后为空的时候返回null

而rs.get方法后面跟的类型是要以你的数据库字段类型为标准,比如我要得到员工号,员工号肯定是整数,所以用getInt,以此类推这段测试代码执行后的结果为:

7369SMITH

得到了员工号为7369,名字为SMITH

2.PreparedStatement

从上面的示例可以看到,我们进行SQL查询是传入了一条写好的固定好了的SQL语句,比如我们现在需要进行下一条查询,必须在重新写一个SQL语句,并且重新编译一次。这样看来效率很差,Statement只适合在静态SQL中使用,为此Java引进了PreparedStatement来做出动态SQL查询的效果。

关于PreparedStatement的原理解释有很多很多,下面我直接引入一段代码直观简介的阐明

1     @Test 2     public void test2(){ 3         //假设查询的工资 4         double salary=4500.0; 5         Connection conn=null; 6         try { 7             conn=DBUtil.getConnection(); 8             String sql="select *from emp_jiawenzhe " 9                     + "where sal>=?";10             //创建PrepareStatement对象11             //发送SQL并建立执行计划12             PreparedStatement ps=conn.prepareStatement(sql);13             //设置参数14             //ps.set类型(?的索引,?的值)15             ps.setDouble(1, salary);16             ResultSet rs=ps.executeQuery();17             while (rs.next()) {18                 System.out.println(rs.getInt("empno"));19                 System.out.println(rs.getString("ename"));20                 21             }22         } catch (SQLException e) {23             24             e.printStackTrace();25             throw new RuntimeException("查询员工失败",e);26         }finally{27             DBUtil.close(conn);28         }29     }

在上面的SQL语句中,可以看懂他的意思就是要查询工资大于某个范围的员工信息,但是这个范围我们并没有写死,而是用"?"作为占位符,也就是说,这个问号的具体值将由后面传入,和Statement的方法一样,我们同样要拿到PreparedStatement的接口的连接对象,调用他的一个set()方法将参数传入,第一个参数是索引值,也就是问号的位置,第二个参数就是实际的值,将实际的值存放到变量之中,这样在修改的时候只要改动就可以了,而不用再去改动SQL语句。

接下来的这个例子,你会看到SQL使用了更多的占位符,更加体现了这种方法的有点

1     @Test 2     public void test03(){ 3         //假设用户传入了如下要添加的数据 4         String ename="唐僧"; 5         String job="领导"; 6         int mgr=0; 7         Date date=new Date(System.currentTimeMillis()); 8         double sal=9000; 9         double comm=3000;10         int deptno=2;11         Connection conn=null;12         try {13             conn=DBUtil.getConnection();14             String sql="insert into emp_jiawenzhe(empno,ename,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) "15                     + "values(emp_jiawenzhe_j.nextval,?,?,?,?,?,?,?)";16             PreparedStatement ps=conn.prepareStatement(sql);17             ps.setString(1, ename);18             ps.setString(2, job);19             ps.setInt(3, mgr);20             ps.setDate(4, date);21             ps.setDouble(5, sal);22             ps.setDouble(6, comm);23             ps.setInt(7,deptno);24             ps.executeQuery();25         } catch (SQLException e) {26     27             e.printStackTrace();28             throw new RuntimeException("增加员工失败",e);29         }finally{30             DBUtil.close(conn);31         }32     }

下面是一条修改的示例:

1     @Test 2     public void test4(){ 3         //假设用户传入了如下要修改的数据 4         int empno=104; 5         String ename="悟空"; 6         String job="保镖"; 7         int mgr=8; 8         Date date =new Date(System.currentTimeMillis()); 9         double sal=5000.0;10         double comm=0;11         int deptno=2;12         Connection conn=null;13         try {14             conn=DBUtil.getConnection();15             String sql="update emp_jiawenzhe set "16                     + "ename=?,"17                     + "job=?,"18                     + "mgr=?,"19                     + "hiredate=?,"20                     + "sal=?,"21                     + "comm=?,"22                     + "deptno=? "23                     + "where empno=?";24             PreparedStatement ps=conn.prepareStatement(sql);25             ps.setString(1, ename);26             ps.setString(2, job);27             ps.setInt(3, mgr);28             ps.setDate(4, date);29             ps.setDouble(5, sal);30             ps.setDouble(6, comm);31             ps.setInt(7, deptno);32             ps.setInt(8, empno);33             ps.executeQuery();34         } catch (SQLException e) {35             36             e.printStackTrace();37             throw new RuntimeException("修改错误",e);38         }finally{39             DBUtil.close(conn);40         }41     }

set方法后面跟的类型和我上面说的get方法是完全一样的

下面是一个删除的示例:

1     @Test 2     public void test5(){ 3         Connection conn=null; 4         int empno=104; 5         try { 6             conn=DBUtil.getConnection(); 7             String sql="delete from emp_jiawenzhe " 8                     + "where empno=? "; 9             PreparedStatement ps=conn.prepareStatement(sql);10             ps.setInt(1, empno);11             ps.executeQuery();12         } catch (SQLException e) {13         14             e.printStackTrace();15             throw new RuntimeException("删除错误",e);16         }finally{17             DBUtil.close(conn);18         }19     }

注意一下这里面的DBUtil就是我之前写的工具类3

3.SQL注入

所谓的SQL注入其实就是程序的一个bug,更准确的说是在使用Statement时产生的这样一个bug,我举个例子加以说明一下,比如你在输入密码的时候,其实你是不知道密码的,你输入的密码是:123 or ‘a’=‘a’;这样输入就是利用了SQL里面的关键字or,因为or后面的表达式是恒成立的,所以这个密码整体就是恒正确的,这样你就会在完全不知道密码的情况下登陆系统

为了解决这个办法,必须使用参数化的SQL,即使用?作为占位符,这样就可以有效避免SQL注入

示例代码:

1 @Test 2     public void test6(){ 3         //假设用户输入的数据如下 4         String username ="admin"; 5         String password="'a' or 'b'='b'"; 6         Connection conn=null; 7         try { 8             conn=DBUtil.getConnection(); 9             String sql="select*from user_jiawenzhe "10                     + "where username=? "11                     + "and password=? ";12             PreparedStatement ps=conn.prepareStatement(sql);13             ps.setString(1, username);14             ps.setString(2, password);15             ResultSet rs= ps.executeQuery();16             while (rs.next()) {17                 System.out.println("登陆成功");18                 19             }20         } catch (SQLException e) {21             22             e.printStackTrace();23             throw new RuntimeException("查询用户失败",e);24         }finally{25             DBUtil.close(conn);26         }27     }

这样系统将不会把or理解为SQL的关键字而仅仅当成普通的字符串。

未完待续!

转载于:https://www.cnblogs.com/jwz-bk/p/5479211.html

你可能感兴趣的文章
ashx.cs 读写session
查看>>
Java版本
查看>>
LINUX手动查看和修改MTU值的方法
查看>>
Linux buffer/cache异同
查看>>
MySQL数据库my.cnf性能参数如何调优
查看>>
特征预处理
查看>>
Setup Apache2 in Debian 9 and enable two ports for two sites
查看>>
商品的价格梯度
查看>>
图形学-剔除
查看>>
人生哲学
查看>>
JAVA调用.NET的WEBSERVICE
查看>>
Selenium+Python浏览器调用:Firefox
查看>>
nohup 详解
查看>>
树莓派实现摄像头监控(使用motion和mjpg-streamer)
查看>>
《转》推荐系统经典论文文献及业界应用
查看>>
webpack的像素转vw单位的loader插件
查看>>
javascript高级程序设计一书----关于创建和对象继承的总结
查看>>
媒体电话
查看>>
Web开发者欣喜若狂的40个UI设计工具和资源
查看>>
整数拼数 C语言版
查看>>