PreparedStatement解决SQL注入、SQL语句批量执行以及如何获取自增主键的值

PreparedStatement的使用

什么是SQL注入?

  • 即本来应该是值的位置,添加进去了SQL语句
    例:——注入的内容:or ‘1’=’1’
    PreparedStatement解决SQL注入、SQL语句批量执行以及如何获取自增主键的值_第1张图片

如何处理?

  • 使用PreparedStatement,将编译期改为预编译
  • 好处:由于创建对象时已经将SQL语句逻辑部分编译完成,所以不会被用户的输入内容所影响
    ,从而解决SQL注入的问题

与statement相比的优势?

——编译时将SQL语句的逻辑锁死
好处:代码结构整洁,不易出错,可以避免SQL注入

什么时候使用?

当SQL语句中有变量时使用PreparedStatement,反之使用Statement
————————————————————————————————————————

package DBCP;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

import org.junit.Test;

public class 模拟登录 {
	@Test
	public void create() {
		try(Connection connection = DBUtils.getConnection()){
			Scanner scanner = new Scanner(System.in);
			System.out.println("输入账号");
			String username = scanner.nextLine();
			System.out.println("输入密码");
			String password = scanner.nextLine();
			/*
			Statement statement = connection.createStatement();
			String sql = "select count(*) from jduser where username='"+username+"' and password='"+password+"' or '1'='1'";
			ResultSet rs = statement.executeQuery(sql);
			*/
			String sql = "select count(*) from jduser where username=? and password=?";
			//预编译的SQL执行对象,创建对象时对SQL语句进行了编译
			/**
			 * 由于创建对象时已经将SQL语句逻辑部分编译完成
			 * 后期不会被用户输入的内容所影响
			 * 从而解决了SQL注入的问题
			 */
			PreparedStatement ps = connection.prepareStatement(sql);
			//setString方法替换掉sql中的?,1代表第一个问号,username代表替换进去的值
			ps.setString(1, username);
			ps.setString(2, password);
			//此时executeQuery方法不需要再传入sql
			ResultSet rs = ps.executeQuery();
			for(;rs.next();) {
				int count = rs.getInt("count(*)");
				System.out.println(count);
				if(count>0) {
					System.out.println("登录成功");
				}else {
					System.out.println("登录失败");
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

附上DBUtils

package DBCP;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;

public class DBUtils工具 {
	//连接池只需要一个,所以放在静态块里,因为静态块只在类加载的时候运行一次
	private static BasicDataSource ds;
	static {
		//读取配置文件
		//创建读取配置文件的对象
		Properties pp = new Properties();
		//通过类加载器来获取文件输入流
		InputStream ips = DBUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
		//加载输入流,抛出异常
		try {
			pp.load(ips);
			//读取数据
			String driver = pp.getProperty("driver");
			String url = pp.getProperty("url");
			String username = pp.getProperty("username");
			String password = pp.getProperty("password");
			/*
			 * System.out.println(driver); 
			 * System.out.println(url);
			 * System.out.println(username); 
			 * System.out.println(password);
			 */
			//______________________________________________________________
			//______________________________________________________________
			//创建连接池对象
			ds = new BasicDataSource();
			//设置数据库连接信息
			ds.setDriverClassName(driver);
			ds.setUrl(url);
			ds.setUsername(username);
			ds.setPassword(password);
			//设置初始连接数量
			ds.setInitialSize(10);
			//设置最大连接数量
			ds.setMaxActive(100);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static Connection getConnection() throws Exception {
		//获取连接,异常抛出
		Connection connection = ds.getConnection();
		System.out.println(connection);	
		return connection;

	}
}

SQL语句批量执行方法

好处:——将执行多条SQL语句时的多次数据传输合并成一次,从而提高执行效率

package DBCP;

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

public class demo {
	public static void main(String[] args) {
		try(Connection connection = DBUtils.getConnection()){
			String sql = "insert into jduser values(null,?,?)";
			//因sql语句中有变量,所以使用预编译方式执行
			PreparedStatement ps= connection.prepareStatement(sql);
			int count=0;
			//批量添加100条数据
			for(int i=0;i<100;i++) {
				count++;
				String username = "name"+count;
				//密码随机
				String password = Integer.toString((int) (Math.random()*1000));
				ps.setString(1, username);
				ps.setString(2, password);
				//添加到批量处理方法addBatch()中
				ps.addBatch();
				//为了防止内存溢出,添加判断,设置每隔50次执行一遍
				//我只设置了100条,不会溢出,当数据多的时候可能会
				if(i%50==0) {
					ps.executeBatch();
				}
			}
			//执行批量处理
			ps.executeBatch();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

获取自增主键的值

package DBCP;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class getKey {
	public static void main(String[] args) {
		try(Connection connection = DBUtils.getConnection()){
			String sql = "insert into jduser values(null,?,?)";
			//sql后面加Statement.RETURN_GENERATED_KEYS,
			//意为返回产生的key
			PreparedStatement ps = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
			Scanner s = new Scanner(System.in);
			String name = s.nextLine();
			String psw = s.nextLine();
			ps.setString(1, name);
			ps.setString(2, psw);
			int row = ps.executeUpdate();
			System.out.println(row);
			//获取主键值的结果集
			ResultSet rs = ps.getGeneratedKeys();
			for(;rs.next();) {
				//从结果集里面得到主键值
				int key = rs.getInt(1);
				System.out.println(key);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

你可能感兴趣的:(mysql,java)