本文共 7127 字,大约阅读时间需要 23 分钟。
理解PreparedSatement的作用,掌握其使用步骤,避免SQL注入问题。
在之前的 JDBC 实现登录案例中,我们发现输入特定密码后可以登录成功。问题分析如下:
// 代码中的SQL语句"SELECT * FROM user WHERE name='" + name + "' AND password='" + password + "';";// 用户输入后变为"SELECT * FROM user WHERE name='hehe' AND password='a' or '1'='1';";
用户输入的内容直接被拼接到 SQL 语句中,导致 SQL 注入问题。
数据库不会直接执行字符串形式的 SQL 语句,而是需要预编译后的 SQL 语句执行。PreparedSatement 类的作用是:
PreparedSatement 的使用步骤:
PreparedSatement 用于执行增删改查操作,执行增删改时使用 executeUpdate()
,执行查询时使用 executeQuery()
。
理解如何使用 PreparedSatement 改写登录案例,防止 SQL 注入问题。
public class Demo02 { public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); System.out.println("请输入账号: "); String name = sc.nextLine(); System.out.println("请输入密码: "); String password = sc.nextLine(); Connection conn = JDBCUtils.getConnection(); String sql = "SELECT * FROM user WHERE name=? AND password=?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, name); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery(); if (rs.next()) { System.out.println("登录成功:" + rs.getString("name")); } else { System.out.println("登录失败!"); } JDBCUtils.close(conn, pstmt, rs); }}
PreparedSatement 的使用步骤:
掌握 PreparedSatement 对于增删改查操作的实现方法。
向 Employee 表中添加记录。
public class Demo01 { public static void main(String[] args) throws SQLException { Connection conn = JDBCUtils.getConnection(); String sql = "INSERT INTO employee (name, age, address) VALUES (?, ?, ?)"; PreparedStatement preSate = conn.prepareStatement(sql); // 插入数据 preSate.setString(1, "张三"); preSate.setInt(2, 30); preSate.setString(3, "北京"); int i1 = preSate.executeUpdate(); System.out.println("插入数据:" + i1); // 关闭资源 JDBCUtils.close(conn, preSate); }}
更新 Employee 表中的记录。
public class Demo01 { public static void main(String[] args) throws SQLException { Connection conn = JDBCUtils.getConnection(); String sql = "UPDATE employee SET address = ? WHERE id = ?"; PreparedStatement preSate = conn.prepareStatement(sql); // 更新数据 preSate.setString(1, "上海"); preSate.setInt(2, 1); int i1 = preSate.executeUpdate(); System.out.println("更新数据:" + i1); // 关闭资源 JDBCUtils.close(conn, preSate); }}
从 Employee 表中删除指定记录。
public class Demo01 { public static void main(String[] args) throws SQLException { Connection conn = JDBCUtils.getConnection(); String sql = "DELETE FROM employee WHERE id = ?"; PreparedStatement preSate = conn.prepareStatement(sql); // 删除数据 preSate.setInt(1, 2); int i1 = preSate.executeUpdate(); System.out.println("删除数据:" + i1); // 关闭资源 JDBCUtils.close(conn, preSate); }}
查询 Employee 表中所有记录。
public class Demo01 { public static void main(String[] args) throws SQLException { Connection conn = JDBCUtils.getConnection(); String sql = "SELECT * FROM employee"; PreparedStatement preSate = conn.prepareStatement(sql); // 执行查询 ResultSet rs = preSate.executeQuery(); while (rs.next()) { System.out.println("id: " + rs.getInt("id") + ", name: " + rs.getString("name") + ", age: " + rs.getInt("age") + ", address: " + rs.getString("address")); } // 关闭资源 JDBCUtils.close(conn, preSate, rs); }}
PreparedSatement 的使用步骤:
掌握 Druid 连接池的使用方法,了解其优势。
Druid 是阿里巴巴开源的数据库连接池,具有高性能、高可用性和丰富的监控功能。
参数名 | 说明 |
---|---|
jdbcUrl | 数据库连接 URL |
username | 数据库用户名 |
password | 数据库密码 |
driverClass | 驱动类名 |
initialSize | 连接池初始连接数量 |
maxActive | 连接池最大连接数 |
maxWait | 获取连接的最大等待时间 |
checkoutTimeout | 获取连接的超时时间 |
通过 properties 文件配置 Druid 参数。
driverClassName=com.mysql.jdbc.DriverjdbcUrl=jdbc:mysql://localhost:3306/day05username=rootpassword=rootinitialSize=5maxActive=10maxWait=3000
public class Demo04 { public static void main(String[] args) throws Exception { InputStream is = Demo04.class.getResourceAsStream("/druid.properties"); Properties pp = new Properties(); pp.load(is); DataSource ds = DruidDataSourceFactory.createDataSource(pp); Connection conn = ds.getConnection(); String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?)"; PreparedStatement pstmt = conn.prepareStatement(sql); // 插入数据 pstmt.setString(1, "张三"); pstmt.setInt(2, 35); pstmt.setDouble(3, 99.5); int i = pstmt.executeUpdate(); System.out.println("影响的行数:" + i); // 关闭资源 pstmt.close(); conn.close(); }}
Druid 连接池的优势:
掌握 JdbcTemplate 的使用方法,了解其与 JDBC 的区别。
JdbcTemplate 对 JDBC 进行了封装,简化了资源管理,避免了手动处理 Statement 和 Connection。
通过 DataSource 对 JdbcTemplate 进行配置,JdbcTemplate 会自动管理数据库连接。
public class Demo04 { public static void main(String[] args) throws Exception { JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource()); String sql = "CREATE TABLE product (pid INT PRIMARY KEY AUTO_INCREMENT, pname VARCHAR(20), price DOUBLE)"; jdbcTemplate.execute(sql); }}
public class Demo05 { public static void main(String[] args) throws Exception { JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource()); String sql = "INSERT INTO product VALUES (NULL, ?, ?)"; jdbcTemplate.update(sql, "iPhone3GS", 3333); // 其他插入操作... }}
public class Demo05 { public static void main(String[] args) throws Exception { JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource()); String sql = "SELECT * FROM product"; List
JdbcTemplate 的优势:
通过学习 PreparedSatement 的使用方法,掌握了如何避免 SQL 注入问题;通过了解连接池的原理,认识到连接池在数据库资源管理中的重要作用;最后,通过 JdbcTemplate 的简化 API,体验了现代化的 JDBC 开发方式。
转载地址:http://syuiz.baihongyu.com/