首先声明,本文只给出代码,并不是做教程用,如有不便之处,还请各位见谅。
PreparedStatement相较于Statement,概括来说,共有三个优势:
1. 代码的可读性和易维护性:PreparedStatement不需要像Statement那样拼接sql语句,而是用?代替,再对其进行赋值,代码简洁易懂,一目了然。
2. 预编译及DB的缓存过程,使得PreparedStatement在效率上高于Statement。
3. 防止SQL注入(这个不太懂,先这样写着吧)
之前在使用Statement时提过,jdbc的过程大致分为6步(也可以说是7步):注册驱动、建立连接、创建Statement、定义SQL语句、执行SQL语句(如有结果集还需遍历)、关闭连接。PreparedStatement和Statement过程大致相当,不同之处在于,先定义SQL语句,再创建PreparedStatement,再设置参数。总结起来,过程如下:
// 1. 注册驱动 // 2. 建立连接 // 3. 定义sql // 4. 创建PreparedStatement // 5. 设置参数 // 6. 执行sql,如果有结果集需遍历并获取 // 7. 关闭资源
下面给出PreparedStatement进行CRUD的代码。
package com.colin.dao; import com.colin.bean.User; import com.colin.util.DBUtil; import java.sql.*; import java.util.*; public class PreparedjdbcTest { /** * 插入一条新记录_PreparedStatement * @param id id 主键 * @param name 姓名 * @param age 年龄 * @throws SQLException */ public static void insert(int id, String name, int age) throws SQLException { long starttime = System.currentTimeMillis(); PreparedStatement preparedStatement = null; Connection connection = null; try { // 1. 注册驱动 // 2. 建立连接 connection = DBUtil.getConnection(); // 3. 定义sql——?是占位符,在设置参数部分会被替换掉 String sql = "insert into user(id, name, age) values(?, ?, ?)"; // 4. 创建PreparedStatement preparedStatement = connection.prepareStatement(sql); // 5. 设置参数 preparedStatement.setInt(1, id); preparedStatement.setString(2, name); preparedStatement.setInt(3, age); // 6. 执行sql,如果有结果集需遍历并获取 int affectrows = preparedStatement.executeUpdate(); System.out.println("affectrows : " + affectrows); } finally { // 7. 关闭资源 DBUtil.closeAll(preparedStatement, connection); } System.out.println("总用时: " + (System.currentTimeMillis() - starttime)); } /** * 修改一条记录 * @param id * @param name * @param age * @throws SQLException */ public static void update(int id, String name, int age) throws SQLException { long starttime = System.currentTimeMillis(); PreparedStatement preparedStatement = null; Connection connection = null; try { connection = DBUtil.getConnection(); String sql = "update user set name = ?, age = ? where id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(3, id); preparedStatement.setString(1, name); preparedStatement.setInt(2, age); int affectrows = preparedStatement.executeUpdate(); System.out.println("affectrows : " + affectrows); } finally { DBUtil.closeAll(preparedStatement, connection); } System.out.println("总用时 : " + (System.currentTimeMillis() - starttime)); } /** * 删除一条记录 * @param id * @throws SQLException */ public static void delete(int id) throws SQLException { long starttime = System.currentTimeMillis(); PreparedStatement preparedStatement = null; Connection connection = null; try { connection = DBUtil.getConnection(); String sql = "delete from user where id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, id); int affectrows = preparedStatement.executeUpdate(); System.out.println("affectrows : " + affectrows); } finally { DBUtil.closeAll(preparedStatement, connection); } System.out.println("总用时 : " + (System.currentTimeMillis() - starttime)); } /** * 查询一条记录 * @param id * @throws SQLException */ public static List<User> selectOne(int id) throws SQLException { List<User> userList = new ArrayList<>(); ResultSet resultSet = null; PreparedStatement preparedStatement = null; Connection connection = null; try { // 1. 注册驱动,建立连接 connection = DBUtil.getConnection(); // 2. 定义SQL String sql = "SELECT id, name, age FROM user WHERE id = ?"; // 3. 创建PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, id); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { User user = new User( resultSet.getInt("id"), resultSet.getString("name"), resultSet.getInt("age") ); userList.add(user); } } finally { DBUtil.closeAll(resultSet, preparedStatement, connection); } return userList; } /** * 查询所有记录 * @throws SQLException */ public static List<User> selectAll() throws SQLException { List<User> userList = new ArrayList<>(); ResultSet resultSet = null; PreparedStatement preparedStatement = null; Connection connection = null; try { // 1. 注册驱动,建立连接 connection = DBUtil.getConnection(); // 2. 定义SQL String sql = "SELECT id, name, age FROM user"; // 3. 创建PreparedStatement preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { User user = new User( resultSet.getInt("id"), resultSet.getString("name"), resultSet.getInt("age") ); userList.add(user); } } finally { DBUtil.closeAll(resultSet, preparedStatement, connection); } return userList; } public static void main(String[] args) throws SQLException { // insert(10,"pestmtName",7); // update(10, "pestmtName2", 8); // delete(8); // List<User> userList = selectOne(1); List<User> userList = selectAll(); System.out.println(userList); } }
——————————补充:关于增删改的自动提交和手动提交————————————
JDBC中当发生使用DML语言(主要是insert update和delete)时,默认是自动提交的,当然也可以设成手动提交。手动提交需要如下代码(放在获取连接之后):
connection.setAutoCommit(false);
此外,在执行完SQL语句,即preparedStatement.executeXXX()时,需要connection.commit()。需要补充的代码较多,以一个手动提交的insert方法为例:
public static void insert(int id, String name, int age) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = DBUtil.getConnection(); connection.setAutoCommit(false); String sql = "insert into user(id, name, age) values(?, ?, ?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, id); preparedStatement.setString(2, name); preparedStatement.setInt(3, age); int affectrows = preparedStatement.executeUpdate(); System.out.println("affectrows : " + affectrows); // 提交前如果发生异常,如throw new RuntimeException()怎么办?回滚 connection.commit(); } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { try { // 别忘了判断connection非空 if (connection != null) { connection.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); } finally { DBUtil.closeAll(preparedStatement, connection); } }
完毕。