JDBC三种编译

来源:互联网 时间:2017-07-27

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

相关阅读:
Top