JavaWeb5.5【JDBC:案例2、PreparedStatement防SQL注入】
CREATE TABLE USER ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR (32), password VARCHAR (32) ); INSERT INTO USER VALUES(NULL, 'zhangsan', '123'); INSERT INTO USER VALUES(NULL, 'lisi', '456');
1 package com.yub4by.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.Statement; 6 7 /* 8 5 JDBC 9 10 1. 概念 11 Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 12 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。 13 各个数据库厂商去实现这套接口,提供数据库驱动jar包。 14 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。 15 16 2. 快速入门 17 步骤 18 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 19 1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下 20 (在模块下新建libs文件夹,与src同级)(建目录方便管理,建不建都行,名称任意) 21 2.在jar包/libs目录上右键-->Add As Library 22 2. 注册驱动 23 3. 获取数据库连接对象 Connection 24 4. 定义sql语句 25 5. 获取执行sql语句的对象 Statement 26 6. 执行sql,接收返回结果 27 7. 处理结果 28 8. 释放资源 29 30 3. 详解JDBC涉及的各个对象 31 (1) DriverManager:驱动管理对象 32 <2> 注册驱动:告诉程序该使用哪一个数据库驱动jar 33 static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。 34 写代码使用: Class.forName("com.mysql.jdbc.Driver"); 35 通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块 36 static { 37 try { 38 java.sql.DriverManager.registerDriver(new Driver()); 39 } catch (SQLException E) { 40 throw new RuntimeException("Can't register driver!"); 41 } 42 } 43 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。 44 <2> 获取数据库连接 45 方法:static Connection getConnection(String url, String user, String password) 46 * url:指定连接的路径 47 * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称 48 * 例子:jdbc:mysql://localhost:3306/hm_db2 localhost=127.0.0.1 49 * 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称 50 * user:用户名 51 * password:密码 52 53 (2) Connection:数据库连接对象 54 <1>获取执行sql的对象 55 Statement createStatement() 56 PreparedStatement prepareStatement(String sql) 57 <2>管理事务 58 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务 59 提交事务:commit() 60 回滚事务:rollback() 61 62 (3) Statement:执行sql的对象 63 <1>执行静态sql语句并返回其生成的结果的对象 64 boolean execute(String sql) :可以执行任意的sql 65 int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句 66 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败 67 ResultSet executeQuery(String sql) :执行DQL(select)语句 68 69 (4) ResultSet:结果集对象,封装查询结果 70 <1> boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true 71 <2> getXxx(参数):获取数据 72 Xxx: 73 代表数据类型 如: int getInt() , String getString() 74 参数: 75 1. int:代表列的编号,从1开始 如: getString(1) 76 2. String:代表列名称。 如: getDouble("balance") 77 <3>注意-正确使用步骤 78 1. 游标向下移动一行 79 2. 判断是否有数据 80 3. 获取数据 81 while(rs.next()){ //循环判断游标是否是最后一行末尾 82 //获取数据 83 int id = rs.getInt(1); 84 String name = rs.getString("name"); 85 double balance = rs.getDouble(3); 86 System.out.println(id + "---" + name + "---" + balance); 87 } 88 89 (5) PreparedStatement:执行sql的对象,是预编译的SQL 90 <1> SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题 91 1. 输入用户随便,输入密码:a' or 'a' = 'a 92 2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 93 <2> 解决sql注入问题:使用PreparedStatement对象来解决 94 <3> 预编译的SQL:参数使用?作为占位符 95 <4> 步骤 96 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 97 2. 注册驱动 98 3. 获取数据库连接对象 Connection 99 4. 定义sql 100 * 注意:sql的参数使用?作为占位符。 101 如:select * from user where username = ? and password = ?; 102 5. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql) 103 6. 给?赋值: 104 * 方法: setXxx(参数1,参数2) 105 * 参数1:?的位置编号,从1开始 106 * 参数2:?的值 107 7. 执行sql,接受返回结果,不需要传递sql语句 108 8. 处理结果 109 9. 释放资源 110 <5> 注意:后期都会使用PreparedStatement来完成增删改查的所有操作 111 1. 可以防止SQL注入 112 2. 效率更高 113 */ 114 public class JDBCDemo1 { 115 public static void main(String[] args) throws Exception { 116 //1 导入驱动jar包 117 118 //2 注册驱动 119 Class.forName("com.mysql.jdbc.Driver"); 120 121 //3 获取数据库连接对象 122 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hm_db2", "root", "root"); 123 // Connection conn = DriverManager.getConnection("jdbc:mysql:///hm_db2", "root", "root"); 124 125 //4 定义sql语句 126 String sql = "update account set balance=500 where id=1"; 127 128 //5 获取执行sql语句的对象 129 Statement stmt = conn.createStatement(); 130 131 //6 执行sql语句,接收返回结果 132 int count = stmt.executeUpdate(sql); 133 134 //7 处理结果 135 System.out.println(count); //1 136 137 //8 释放资源 138 stmt.close(); 139 conn.close(); 140 141 } 142 }