2022-8-19 第六组 JDBC(2)

PreparedStatement:执行sql的对象

1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

1. 输入用户随便,输入密码:a' or 'a' = 'a
2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 
3. 解决sql注入问题:使用PreparedStatement对象来解决
4. 预编译的SQL:参数使用?作为占位符

2. 步骤:

1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
	* 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
5. 获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql) 
6. 给?赋值:
	* 方法: setXxx(参数1,参数2)
	* 参数1:?的位置编号 从1 开始
	* 参数2:?的值
7. 执行sql,接受返回结果,不需要传递sql语句
8. 处理结果
9. 释放资源

3. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作

1. 可以防止SQL注入
2. 效率更高

抽取JDBC工具类 : JDBCUtils

目的:简化书写

分析:

1. 注册驱动也抽取
2. 抽取一个方法获取连接对象
	* 需求:不想传递参数(麻烦),还得保证工具类的通用性。
	* 解决:配置文件
		jdbc.properties
			url=
			user=
			password=
3. 抽取一个方法释放资源

代码实现:

public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
 * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
 */
static{
    //读取资源文件,获取值。
    try {
        //1. 创建Properties集合类。
        Properties pro = new Properties();
        //获取src路径下的文件的方式--->ClassLoader 类加载器
        ClassLoader classLoader = JDBCUtils.class.getClassLoader();
        URL res  = classLoader.getResource("jdbc.properties");
        String path = res.getPath();
        System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
        //2. 加载文件
        pro.load(new FileReader(path));
        //3. 获取数据,赋值
        url = pro.getProperty("url");
        user = pro.getProperty("user");
        password = pro.getProperty("password");
        driver = pro.getProperty("driver");
        //4. 注册驱动
        Class.forName(driver);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

获取连接

public static Connection getConnection() throws SQLException {

    return DriverManager.getConnection(url, user, password);
}

/**
 * 释放资源
 * @param stmt
 * @param conn
 */
public static void close(Statement stmt,Connection conn){
    if( stmt != null){
        try {
            stmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    if( conn != null){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

JDBC控制事务:

1. 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

2. 操作:

1. 开启事务
2. 提交事务
3. 回滚事务

3. 使用Connection对象来管理事务

* 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
	* 在执行sql之前开启事务
* 提交事务:commit() 
	* 当所有sql都执行完提交事务
* 回滚事务:rollback() 
	* 在catch中回滚事务

4. 代码:

public class JDBCDemo10 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;

        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);

            //2.定义sql
            //2.1 张三 - 500
            String sql1 = "update account set balance = balance - ? where id = ?";
            //2.2 李四 + 500
            String sql2 = "update account set balance = balance + ? where id = ?";
            //3.获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //4. 设置参数
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);

            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);
            //5.执行sql
            pstmt1.executeUpdate();
            // 手动制造异常
            int i = 3/0;

            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
        } catch (Exception e) {
            //事务回滚
            try {
                if(conn != null) {
                    conn.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtils.close(pstmt1,conn);
            JDBCUtils.close(pstmt2,null);
        }
    }

}
posted @ 2022-08-19 21:37  阿萨德菩提子  阅读(25)  评论(0编辑  收藏  举报