标签:jdbc
一、指定SQL语句中的变量
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)
boolean |
execute()
Executes the SQL statement in this PreparedStatement object, which may be any kind of SQL statement.
|
ResultSet |
executeQuery()
Executes the SQL query in this PreparedStatement object and returns the ResultSet object
generated by the query.
|
int |
executeUpdate()
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT , UPDATE or DELETE ;
or an SQL statement that returns nothing, such as a DDL statement.
|
void |
setDouble(int parameterIndex,
double x)
Sets the designated parameter to the given Java double value.
|
void |
setFloat(int parameterIndex,
float x)
Sets the designated parameter to the given Java float value.
|
void |
setInt(int parameterIndex,
int x)
Sets the designated parameter to the given Java int value.
|
void |
setLong(int parameterIndex,
long x)
Sets the designated parameter to the given Java long value.
|
void |
setNull(int parameterIndex,
int sqlType)
Sets the designated parameter to SQL NULL .
|
void |
setShort(int parameterIndex,
short x)
Sets the designated parameter to the given Java short value.
|
void |
setSQLXML(int parameterIndex, SQLXML xmlObject)
Sets the designated parameter to the given java.sql.SQLXML object.
|
void |
setString(int parameterIndex, String x)
Sets the designated parameter to the given Java String value.
|
void |
setURL(int parameterIndex, URL x)
Sets the designated parameter to the given java.net.URL value
|
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语句
参考资料:
04.JDBC编程之指定变量&批处理
标签:jdbc
原文地址:http://blog.csdn.net/u012637501/article/details/45340581