使用JDBC PreparedStatement 修正【SQL注入问题】---- 附有SQL交互超详细Demo !!

想了解JDBC的一些基础知识的同学可以回看:解析JDBC指令 【增删查改的使用】

表示预编译的 SQL 语句的对象

使用PreparedStatement替代Statement的原因

  • Statement有sql注入问题
  • PreparedStatement可以通过规范sql解决sql注入问题
  • 设置占位符参数更灵活

SQL注入问题

因为sql的获取是通过字符串拼接的,当追加OR 1 = 1,整个sql的逻辑会返回true,则会失去判断作用

//sql注入问题demo
ResultSet executeQuery = conn.createStatement().executeQuery("SELECT userno FROM user WHERE username= 'scott', password ='tiger' OR 1 = 1");
if (executeQuery.next()) {
    System.out.println("登陆成功!");
}

常用方法

说明
executeUpdate()没有参数,更新操作后,返回我们数据库响应的行数
executeQuery()没有参数,返回我们数据库查询结果集
setInt()将指定参数设置为给定 Java int 值。内部会自动转成数据库数据类型
setString()将指定参数设置为给定 Java String 值
setObject(int parameterIndex, Object x)使用给定对象设置指定参数的值。(内部会obj转成对应的数据类型 number , varchar2 )
close()释放资源

Demo

增删查改

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import cn.szsxt.utils.JdbcUtils;


public class Demo {

	@Test
	public void demo01() {

		// 添加
		// 获取 conn 连接对象
		Connection conn = JdbcUtils.getConn();
		// 准备sql ? 占位符
		String sql = "insert into t_user(name,pwd) values (?,?)";
		// 获取 ps对象
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			// 设置sql 的参数
			ps.setString(1, "马云");
			// setOjb 内部转成 指定的 数据库的数据类型
			ps.setObject(2, "alibaba");
			// 执行sql update方法
			// 更新后数据库响应的行数
			int update = ps.executeUpdate();// ps 的方法是 executeUpdate()

			// st 的方法是 executeUpdate(sql) 如果调用 st的更新方法会出错

			// 处理结果
			if (update > 0) {
				System.out.println("添加成功 ");
			} else {
				System.out.println("添加失败...");
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 释放资源
		finally {
			JdbcUtils.close(ps, conn);
		}
	}

	@Test
	public void demo02() {

		// 修改操作
		// 获取 conn 连接对象
		Connection conn = JdbcUtils.getConn();
		// 准备sql
		String sql = "update t_user set name = ? ,pwd = ? where id = ?";
		// 获取 ps对象
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			// 设置sql的参数 从左 往 有设置 数据
			ps.setString(1, "scott");
			ps.setString(2, "tiger");
			ps.setInt(3, 2);
			// 执行sql update方法
			int update = ps.executeUpdate();
			// 处理结果
			if (update > 0) {

				System.out.println("修改成功 ...");
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 释放资源
		finally {
			JdbcUtils.close(ps, conn);
		}
	}

	@Test
	public void demo03() {

		// 删除操作
		// 获取 conn 连接对象
		Connection conn = JdbcUtils.getConn();
		// 准备sql
		String sql = "delete from t_user  where id = ?";
		// 获取 ps对象
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			// 设置sql的参数 从左 往 有设置 数据
			ps.setInt(1, 1);
			// 执行sql update方法
			int update = ps.executeUpdate();
			// 处理结果
			if (update > 0) {

				System.out.println("删除成功 ...");
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 释放资源
		finally {
			JdbcUtils.close(ps, conn);
		}
	}
	
	
	@Test 
	public void demo04() {
		
		// 查询操作 
		
		Connection conn = JdbcUtils.getConn();
		
		String sql = "select * from t_user";
		PreparedStatement ps = null;
		
		ResultSet rs = null;
		try {
			 ps = conn.prepareStatement(sql);
			 
			 // ps 设置参数 如果没有就不设置  
			
			 // ruseltSet 查询返回的结果集  可以从结果集中 获取 查询表的数据 
			 rs = ps.executeQuery();
			 
			 // next() 判断  查询结果中是否 有数据  
			 // while 循环遍历   
			 while (rs.next()) {
				
				 // rs中 有getXXx 方法获取  列的中数据  
				 // 可以通过 索引或者列名获取 (类名忽略大小写 )
				 String name = rs.getString("name");
				 String pwd = rs.getString("pwd");
				 
				 System.out.println(name + "\t" +pwd);
				 
			}
			 
			 
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			JdbcUtils.close(rs, ps, conn);
		}
		
	}
}

data数据的数据库交互

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

import cn.szsxt.utils.JdbcUtils;


public class Demo {

	@Test
	public void demo01() {
		
		 // 添加  date 数据类型到数据库 
		// 获取 conn 连接对象 
		Connection conn = JdbcUtils.getConn();
		// 准备sql 
		String sql = "insert into t_user(name,bir) values (?,?)";
		
		// 获取 ps对象 
		PreparedStatement ps = null;
		try {
			 ps = conn.prepareStatement(sql);
			 // 设置sql的参数  参数的设置 要和数据库中的数据类型一致 
			 // int --> number    string --> varchar2 
			 // java.sql.date(是sql包下面的 date ) - > 数据库中 date
			 
			 ps.setString(1, "张无忌");
	
			 // sql.Date 构造 需要给 long 值   
			 Date date = new Date(709789070987L);
			 ps.setDate(2, date);

			 // 执行sql update方法
			 int update = ps.executeUpdate();
			 
			 // 处理结果 
			 if (update > 0) {
				System.out.println("添加成功...");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		// 释放资源
		finally {

			JdbcUtils.close(ps, conn);
		}
	}
	
	@Test 
	public void demo02() {
		
		// 查询操作  查询 获取 数据库中的date类型数据 
		
		Connection conn = JdbcUtils.getConn();
		
		String sql = "select name,bir from t_user where id = ?";
		PreparedStatement ps = null;
		
		ResultSet rs = null;
		try {
			 ps = conn.prepareStatement(sql);
			 
			 // ps 设置参数 如果没有就不设置  
			 ps.setInt(1, 3);
			
			 // ruseltSet 查询返回的结果集  可以从结果集中 获取 查询表的数据 
			 rs = ps.executeQuery();
			 
			 // next() 判断  查询结果中是否 有数据  
			 
			 // while 循环遍历   
			 while (rs.next()) {
				
				 // rs中 有getXXx 方法获取  列的中数据  
				 // 可以通过 索引或者列名获取 (类名忽略大小写 )
				 String name = rs.getString("name");
				 
				 // 获取数据的时候  
				 // 获取的方法 是 getXXX() 要和 数据库的数据 类型要一致 
				 
				 Date date = rs.getDate("bir");
				 System.out.println(name + "\t" +date);
				 
			}
			 
		} catch (SQLException e) {
			e.printStackTrace();
		}
		finally {
			JdbcUtils.close(rs, ps, conn);
		}
	}
}

图片的数据交互

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import cn.szsxt.utils.JdbcUtils;


public class Demo {

	@Test
	public void demo01() {

		// 添加 date 数据类型到数据库
		// 获取 conn 连接对象
		Connection conn = JdbcUtils.getConn();
		// 准备sql
		String sql = "insert into t_user(name,img) values (?,?)";

		// 获取 ps对象
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			// 设置sql的参数参数的设置要和数据库中的数据类型一致

			// 图片存储是二进制文件blob 数据类型

			ps.setString(1, "张无忌");

			// 可以读取图片 到输入流 把 这个流存到 数据中

			// 读取图片
			File f = new File("src/zm.jpg");
			// 选择流
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(f);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			ps.setBlob(2, fis);

			// 执行sql update方法
			int update = ps.executeUpdate();

			// 处理结果
			if (update > 0) {
				System.out.println("添加成功...");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 释放资源
		finally {

			JdbcUtils.close(ps, conn);
		}
	}

	@Test
	public void demo02() {

		// 查询操作 查询 获取 数据库中的 图片

		Connection conn = JdbcUtils.getConn();

		String sql = "select name,img from t_user where id = ?";
		PreparedStatement ps = null;

		ResultSet rs = null;
		try {
			ps = conn.prepareStatement(sql);

			// ps 设置参数 如果没有就不设置
			ps.setInt(1, 1);

			// ruseltSet 查询返回的结果集 可以从结果集中 获取 查询表的数据
			rs = ps.executeQuery();

			// next() 判断 查询结果中是否 有数据

			// while 循环遍历
			while (rs.next()) {

				// rs中 有getXXx 方法获取 列的中数据
				// 可以通过 索引或者列名获取 (类名忽略大小写 )
				String name = rs.getString("name");
				System.out.println(name);
				// 获取数据的时候
				// 获取的方法 是 getXXX() 要和 数据库的数据 类型要一致

				Blob blob = rs.getBlob("img");

				// blob 是二进制数据类型 可以 转成 输入 流
				InputStream is = blob.getBinaryStream();

				String path = "src/a.jpg";
				writeImage(is, path);

			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.close(rs, ps, conn);
		}

	}

	/**
	 * 图片数据库中的图片 保存到本地
	 * 
	 * @param is   输入流
	 * @param path 保存到本地的 图片 路径
	 */
	private void writeImage(InputStream is, String path) {

		// 建立联系
		File f = new File(path);

		// 选择流
		BufferedOutputStream fos = null;
		try {
			fos = new BufferedOutputStream(new FileOutputStream(f));

			// 读写操作
			byte[] buffer = new byte[1024];
			int len = 0;

			// -1 判断是否读 到 文件的末尾
			while ((len = is.read(buffer)) != -1) {

				fos.write(buffer, 0, len);
			}
			fos.flush();

		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(" 保存完毕");
	}

}

文本的数据交互

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import cn.szsxt.utils.JdbcUtils;



public class Demo {

	@Test
	public void demo01() {

		// 获取conn
		Connection conn = JdbcUtils.getConn();

		String sql = "insert into t_user(name,myinfo) values (?,?)";

		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);

			ps.setString(1, "赵敏");

			// CLob 设置大文本数据
			FileReader fr = new FileReader(new File("src/a.txt"));
			ps.setClob(2, fr);

			// 更新操作
			int update = ps.executeUpdate();

			if (update > 0) {

				System.out.println("插入成功");
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		} finally {

			JdbcUtils.close(ps, conn);
		}

	}
	
	@Test 
	public void demo02() {
		
		// 获取conn
		Connection conn = JdbcUtils.getConn();


		String sql = "select name,myinfo from t_user where id = ? ";

		PreparedStatement ps = null;
		ResultSet rs = null;
			try {
				ps = conn.prepareStatement(sql);
				
				ps.setInt(1, 4);
				
				// 查询 
				 rs = ps.executeQuery();
				
				if (rs.next()) {
					
					String name = rs.getString("name");
					System.out.println(name);

					//是大文本数据   可以获取字符输入流 
					Clob clob = rs.getClob("myinfo");

					String str = writeString(clob);
					System.out.println(str);
					
				}
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				JdbcUtils.close(rs, ps, conn);
			}
	}

	/**
	    *  读取  大文本中的字符
	 * @param clob   大文本 数据类型  
	 * @return
	 */
	private String writeString(Clob clob) {

		// 获取字符串输入流 
		try {
			StringBuilder sb = new StringBuilder();
			Reader reader = clob.getCharacterStream();
		
			// reader 转成  字符缓冲 br 
			BufferedReader br = new BufferedReader(reader);		
			// readLine() 读取一行  
			String msg = null;
			// 读取到的字符串 赋值给 msg 如果msg 不为null 继续 循环读取  
			while ((msg = br.readLine()) != null) {
				
				// msg 是有多行数据  要把多行数据 拼成一个字符串 可以 StringBuilder 
				sb.append(msg + "\r\n");
			}
			return sb.toString();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值