JDBC三种编译

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进行预编译比较安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值