jdbc预编译

详见:[url]http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp20[/url]

JAVA_JDBC预编译 相关知识点
什么是预编译语句?
预编译语句PreparedStatement是java.sql中的一个接口,它是Statement的子接口。通过Statement对象执行sql语句时,需要将sql语句发送给DBMS,由DBMS首先进行编译再执行(在创建通道的时候并不进行sql的编译工作,事实上也无法进行编译)。而通过PreparedStatement不同,在创建PreparedStatement对象时就指定了sql语句,该语句立即发送给DBMS进行编译,当该语句被执行时,DBMS直接运行编译后的sql语句,而不需要像其他sql语句那样首先将被编译。

什么时候使用预编译语句?
当语句格式固定的时我们倾向于使用PreparedStatement,只有当语句格式无法预见时,才考虑使用Statement。
一般在考虑反复使用一个sql语句时才使用预编译,预编译语句常常放在一个循环中使用(在这种情况下预编译的优势就很明显了),通过反复设置参数从而达到多次使用该语句;还有一个原因就是防止sql注入漏洞。

为什么使用预编译语句?
1、提高效率
当需要数据库进行数据插入、更新或者删除的时候,程序给发送整个sql语句给数据库处理和执行。数据库处理一条sql语句,需要完成对sql语句的解析、检查语法以及生成代码;一般来说,处理时间要比执行sql的时间长。预编译语句在创建的时候就已经将sql语句发送给了DBMS,完成了解析、检查语法以及生成代码的过程。因此,当一个sql语句需要执行多次时,使用预编译语句可以减少处理时间,提高执行效率。
2、提高安全性
恶意的sql语句
String sql = “select * from user_tb where username= ‘”+username+”’ and password = ‘”+password+”’;
如果我们把[‘or’1’=’1]作为password传入,用户名随意,那么就可以随意登陆了。更有甚者,把[‘;drop table user_tb;]作为password传入,这就严重危害了数据库安全了。而如果你使用预编译语句,你传入的任何内容就不会和原来的语句发生任何匹配的关系,只要全是用预编译语句,你就用不着对传入的数据进行任何的过滤。(暂时没想明白,个人认为过滤还是需要的)
<think>嗯,用户问的是关于JDBC预编译SQL的问题。我需要先回忆一下JDBC的相关知识。预编译SQL主要是通过PreparedStatement来实现的,和普通的Statement有什么不同呢?首先,预编译可以提高性能,因为SQL语句在数据库中被预先编译,多次执行时不需要重复编译。然后,防止SQL注入攻击,因为参数化处理,用户输入不会被当作SQL的一部分执行。那具体怎么使用呢?应该先创建PreparedStatement对象,使用占位符?来代替参数,然后通过setXXX方法设置参数。比如,执行插入操作,用conn.prepareStatement("INSERTINTO users(name, age) VALUES(?,?)");然后设置参数,执行executeUpdate。 然后要解释为什么预编译能防止SQL注入,比如当用户输入中有引号或者特殊字符时,预编译会将这些作为参数处理,而不是拼接到SQL语句中,避免了恶意代码的执行。 可能用户还关心预编译的优缺点,或者和Statement的区别。需要提到性能优势,安全性,以及可读性等方面。另外,可能需要注意预编译的SQL在某些情况下是否可以被数据库重用,比如是否缓存PreparedStatement。然后按照要求,给出代码示例,展示如何正确使用PreparedStatement,包括连接数据库、设置参数、执行查询等步骤。同时,对比不安全的Statement方式,说明两者的区别。最后,相关问题要围绕JDBC预编译展开,比如原理、防止注入的方式、优缺点、与存储过程的比较,以及参数设置方法。这些问题可以帮助用户深入理解预编译的重要性及使用场景。</think>JDBC预编译SQL的实现方式是通过`PreparedStatement`接口完成的,以下是实现步骤和原理: ```java // 1. 创建预编译语句 String sql = "SELECT * FROM users WHERE email = ? AND status = ?"; try (Connection conn = DriverManager.getConnection(url, user, password); PreparedStatement pstmt = conn.prepareStatement(sql)) { // 2. 设置参数(索引从1开始) pstmt.setString(1, "user@example.com"); pstmt.setInt(2, 1); // 3. 执行查询 try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { // 处理结果集 } } } ``` **为什么需要预编译SQL:** 1. **防止SQL注入**:参数值通过类型安全的方式绑定,不会被解释为SQL语法 2. **性能优化**:数据库会缓存预编译的查询计划,重复执行时无需重新解析SQL 3. **类型安全**:自动处理数据类型转换(如Date转SQL DATE) 4. **可读性**:使用占位符比字符串拼接更清晰 **典型错误示例(不安全的方式):** ```java // 危险!容易导致SQL注入 String input = "'; DROP TABLE users;--"; String badSql = "SELECT * FROM users WHERE name = '" + input + "'"; Statement stmt = conn.createStatement(); stmt.executeQuery(badSql); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值