JDBC三种编译

来源:互联网 发布:阜阳市工商局网络监管 编辑:程序博客网 时间:2024/06/06 14:16

JDBC中有三个主要用于编译的API,分别是Statement接口、PrepareStatement接口以及CallableStatement接口。

1、Statement接口编译
手动连接数据库,创建一个表

package com.wk.jdbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;import org.junit.Test;/* * 使用jdbc执行sql语句 *  */public class JDBC2 {    private String user = "wk";    private String psw = "199645";    //连接数据库的url    private String url = "jdbc:mysql://localhost:3306/myfirst";    @Test    public void test1(){        Statement state = null; //com.sql.Statement        Connection conn = null;        //加载驱动        //发送sql语句        String sql = "create table teacher("+                "id int primary key auto_increment,"+                "name varchar(10),"+                 "class varchar(20));";        try {            Class.forName("com.mysql.jdbc.Driver");            conn = DriverManager.getConnection(url,user,psw);            state = conn.createStatement();            //更新行数            int count = state.executeUpdate(sql);            System.out.println(count);        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            try {                if(state != null)                state.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            try {                if(conn != null)                conn.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}

2、PrepareStatement预编译,该接口是Statement的子接口,在编译sql语句时用占位符?作为参数,在执行前设置参数。
这里使用JdbcUtil工具连接数据库,新增一条记录(可参考——-——JDBC技术)

package com.wk.jdbc;import java.sql.Connection;import java.sql.SQLException;import org.junit.Test;import java.sql.PreparedStatement;import com.wk.jdbc_util.JdbcUtil;/* * 使用预编译PrepareStatement执行sql语句 *  */public class JDBC4 {    @Test    public void test(){        Connection conn = null;        PreparedStatement pst = null;        try {        conn = JdbcUtil.getConnection();        String sql = "UPDATE STUDENT SET NAME = ? WHERE id = ?";        pst = conn.prepareStatement(sql);        //设置参数,参数索引从1开始        pst.setString(1, "张三");        pst.setInt(2, 1);        int count = pst.executeUpdate();        System.out.println(count);        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtil.close(conn, pst);        }    }}

3、前两种是增删改操作,只返回一个更新记录的行数,如果用于查询则返回一个结果集封装在ResultSet对象中。查询一个表操作如下

package com.wk.jdbc;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import org.junit.Test;import com.wk.jdbc_util.JdbcUtil;/* * jdbc执行DQL查询语句 *  */public class JDBC3 {    @Test    public void test1(){        Connection conn = null;        Statement state = null;        ResultSet result = null;        try {            conn = JdbcUtil.getConnection();            state = conn.createStatement();            //查询语句            String sql = "select *from student";            //执行sql,返回数据保存在ResultSet对象中            result = state.executeQuery(sql);            while(result.next()){                //列索引取法                //注意这里的游标从1开始,代表表中的第一个字段,getXXX()获取相应数据类型                int id = result.getInt(1);                String name = result.getString(2);                int age = result.getInt(3);                String addr = result.getString(4);                System.out.println(id+"-"+name+"-"+"-"+age+"-"+addr);            }        } catch (SQLException e) {            e.printStackTrace();        }finally{            JdbcUtil.close(conn, state, result);        }       }   }

4、CallableStatement编译结果集。属于PrepareStatement接口的子接口,首先在数据库中创建一个存储过程(可参考——-——JDBC技术)

DELIMITER $CREATE PROCEDURE insertAndQuery()BEGIN    INSERT INTO student (NAME,age,address) VALUES ('李明',20,'英语教材');    SELECT *FROM student WHERE NAME='李明';END $

然后在程序中只需要调用SQL语句“CALL insertAndQuery()”即可,这是无参数的存储过程,下面看一个带有输入输出参数的存储过程

DELIMITER $CREATE PROCEDURE pro_findById(IN sid INT,OUT sname VARCHAR(20))BEGIN     SELECT NAME INTO sname FROM student WHERE id=sid; -- 表示根据id找姓名END$

使用CallableStatement来调用存储过程

package com.wk.jdbc;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.SQLException;import org.junit.Test;import com.wk.jdbc_util.JdbcUtil;/* *  * 使用CallableStatement对象调用存储过程 */public class JDBC6 {    @Test    public void test(){        Connection conn = null;        CallableStatement cs = null;        try {            conn = JdbcUtil.getConnection();            //第一个占位符为输入参数,第二占位符为输出参数                String sql = "CALL pro_findById(?,?)";            cs = conn.prepareCall(sql);            //设置输入参数            cs.setInt(1, 2);            //注册输出参数            cs.registerOutParameter(2, java.sql.Types.VARCHAR);            //执行查询            cs.executeQuery();            //用变量接收输出参数的值,调用getXXX()方法,参数和占位符所在位置对应            String result = cs.getString(2);            System.out.println(result);        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtil.close(conn, cs);        }    }}

5、Statement中的注入问题
这是一个用Statement查询的例子,当输入正确的用户名和密码会返回succeed,否则返回failed,与数据库比较没有该记录,所以返回的是failed
这里写图片描述

package com.wk.jdbc;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import org.junit.Test;import com.wk.jdbc_util.JdbcUtil;/* *  * Statement的注入问题 */public class JDBC5 {    private String name = "liming";    private String passward = "13456";    @Test    public void test(){        Connection conn = null;        Statement stat = null;        ResultSet rs = null;        try {            conn = JdbcUtil.getConnection();            stat = conn.createStatement();            String sql = "SELECT *FROM admin WHERE userName='"+name+"' AND password='"+passward+"'";            rs = stat.executeQuery(sql);            if(rs.next()){                System.out.println("successed");            }else{                System.out.println("failed");            }            } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            try {                if(rs!=null)                    rs.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            JdbcUtil.close(conn, stat);        }    }}
failed   //返回值

如果输入一个已存在用户

private String name = "小明";private String passward = "123456";succeed//返回值

如果再次进行修改

private String name = "小明' OR 1=1 -- ";private String passward = "3456";succeed   //密码错误依然可以验证成功

这就是Statement中的注入问题,因为“1=1”在sql中是恒成立的,并且后面内容被注释所以输入任何内容都可以访问数据库,所以应该选择PrepareStatement进行预编译比较安全

原创粉丝点击