04.JDBC编程之指定变量&批处理
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.PreparedStatement接口 PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。 包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。另外,作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。三种方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数。 由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。为此,在JDBC应用中应该始终以PreparedStatement代替Statement,即尽量不要使用Statement。 Interface PreparedStatement(java.sql)
2.优点
(1)代码的可读性和可维护性 虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次。下面分别使用Statement、PrepareStatement执行一条SQL语句
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
//stmt是Statement对象实例 perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate(); //prestmt是 PreparedStatement 对象实例
(2)PreparedStatement尽最大可能提高性能 语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个函数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert into tb_name (col1,col2) values ('11','22');
insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果,以保存有更多的空间存储新的预编译语句。
(3)最重要的一点是极大地提高了安全性 即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道. String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'"; 如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名随意,看看会成为什么? select * from tb_name = '随意' and passwd = '' or '1' = '1'; 因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者: 把[';drop table tb_name;]作为varpasswd传入进来,则: select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行. 而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.
3.源码实战:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /*MySQL数据库编程 * 实例(4):使用PreparedStatement灵活指定SQL语句中的变量*/ public class JDBC_PreparedStatement { public static void main(String[] args) { if(args.length!=3) //输入不正确,非正常退出 { System.out.println( "Parament Error,Please Input Again!"); System.exit(-1); } String nameParam=args[0]; //获取命令行第一个参数 int ageParam=Integer.parseInt(args[1]); //获取命令行第二个参数,并转换为整型 int scoreParam=Integer.parseInt(args[2]);//获取命令行第三个参数,并转换为整型 //0.连接数据库相关参数 String url="jdbc:mysql://localhost:3306/jdbc_test_db"; //数据库URL(资源定位唯一标识符) String DBusername="root"; //数据库用户名 String DBpasswd="111111"; //数据库密码 //1.加载数据库驱动,将Driver注册到DriverManager中 try{ Class.forName("com.mysql.jdbc.Driver"); }catch(ClassNotFoundException e){ e.printStackTrace(); } //2.通过数据库URL连接到数据库 Connection conn=null; PreparedStatement prestmt=null; try{ conn=DriverManager.getConnection(url, DBusername, DBpasswd); //3.获取PreparedStatement对象 String sql="insert into test(name,age,score) values(?,?,?)"; prestmt=conn.prepareStatement(sql); prestmt.setString(1, nameParam); //分别给变量设值 prestmt.setInt(2, ageParam); prestmt.setInt(3, scoreParam); prestmt.execute(); }catch(SQLException e){ e.printStackTrace(); } //5.释放JDBC资源 if(prestmt!=null) //关闭声明 { try{ prestmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn!=null) //关闭连接 { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } }(1)设置命令行参数 右击工程->Run as->Open Run Dialog->Main Class选择"JDBC_PreparedStatement"
(2)运行结果
二、批处理SQL语句 (1)源代码
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /*MySQL数据库编程 * 实例(5):JDBC批量处理DML语句.分别尝试Statement、PreparedStatement*/ public class JDBC_Batch { public static void main(String[] args) { //0.连接数据库相关参数 String url="jdbc:mysql://localhost:3306/jdbc_test_db"; //数据库URL(资源定位唯一标识符) String DBusername="root"; //数据库用户名 String DBpasswd="111111"; //数据库密码 //1.加载数据库驱动,将Driver注册到DriverManager中 try{ Class.forName("com.mysql.jdbc.Driver"); }catch(ClassNotFoundException e){ e.printStackTrace(); } //2.通过数据库URL连接到数据库 Connection conn=null; PreparedStatement prestmt=null; try{ conn=DriverManager.getConnection(url, DBusername, DBpasswd); //3.获取PreparedStatement对象 String sql="insert into test(name,age,score) values(?,?,?)"; prestmt=conn.prepareStatement(sql); prestmt.setString(1,"aaa"); prestmt.setInt(2, 19); prestmt.setInt(3, 55); prestmt.execute(); //a.添加第一条插入记录 prestmt.setString(1,"bbb"); prestmt.setInt(2, 20); prestmt.setInt(3, 66); prestmt.execute(); //a.添加第二条插入记录 prestmt.setString(1,"ccc"); prestmt.setInt(2, 21); prestmt.setInt(3, 77); prestmt.execute(); //a.添加第三条插入记录 }catch(SQLException e){ e.printStackTrace(); } //5.释放JDBC资源 if(prestmt!=null) //关闭声明 { try{ prestmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn!=null) //关闭连接 { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } }
(2)运行结果
说明分析: 这里使用的是SQL语句静态插入数据,我们也可以使用Statement的addBatch方法实现JDBC批量处理SQL语句
Statement stmt=conn.createStatement();
stmt.addBatch("insert into test(name,age,score) values('ppp',30,88)");
stmt.addBatch("insert into test(name,age,score) values('ooo',31,89)");
stmt.addBatch("insert into test(name,age,score) values('qqq',32,90)");
stmt.executeBatch(); //批量执行SQL语句
本站文章为和通数据库网友分享或者投稿,欢迎任何形式的转载,但请务必注明出处.
同时文章内容如有侵犯了您的权益,请联系QQ:970679559,我们会在尽快处理。