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,我们会在尽快处理。