Java PreparedStatement
Java PreparedStatement层次结构
//Method :
public PreparedStatement prepareStatement(String query)throws SQLException{}
//Usage :
Connection con = DriverManager.getConnection ("jdbc:mysql://localhost:3306/customerdb", "root", "root");
PreparedStatement ps = con.prepareStatement("select id, firstname, lastname, email, birthdate from tblcustomer");
PreparedStatement的优势
我们可以将方法分为不同的类别。
PreparedStatement方法
Java PreparedStatement就像一个Statement,它是Java JDBC Framework的一部分。
它用于对数据库执行分类操作。
1.执行查询
以下所有方法都有2个参数。
第一个参数是参数索引,第二个参数是参数值。
PreparedStatement扩展了Statement接口。
PreparedStatement支持参数化查询,因此被认为更安全。
PreparedStatement还可以防止SQL注入攻击。我们可以通过调用Connection的prepareStatement(String query)方法来获得PreparedStatement的实例,如下所示。
PreparedStatement可以用于参数化查询和普通查询。
PreparedStatement的查询性能优于语句的查询性能。
可以重新使用PreparedStatement实例以执行具有不同参数的同一查询。
PreparedStatement使应用程序免受SQL Injection攻击。
ResultSet executeQuery():此方法用于通过PreparedStatement对象执行读取操作。
它返回一个ResultSet的实例,用于获取数据。
注意:parameterIndex值从1开始,所有这些方法都抛出SQLException。
2.将参数值传递给查询
我们将使用MySQL数据库来演示PreparedSatement的用法。
使用下面的DB脚本创建数据库,表和示例数据。
create database customerdb; use customerdb; create table tblcustomer( id integer AUTO_INCREMENT primary key, firstname varchar(32), lastname varchar(32), email varchar(32), birthdate datetime ); insert into tblcustomer (id,firstname,lastname,email,birthdate) values(1,'Ricky','Smith','[email protected]','2001-12-10');
数据库连接信息:
MySql数据库的名称:customerdb IP:本地主机端口:3306用户名:root密码:root
Maven依赖关系:
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
Java PreparedStatement示例
在这种情况下,我们将从tblcustomer中获取具有指定ID的行。
查询将返回单行。
package com.theitroad.examples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class PreparedStatementDemo {
public static void main(String[] args) throws Exception {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
int customerId = 1;
String query = "select id, firstname, lastname, email, birthdate from tblcustomer where id = ?";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/customerdb", "root", "root");
ps = con.prepareStatement(query);
ps.setInt(1, customerId);
rs = ps.executeQuery();
while (rs.next()) {
System.out.println("Id:" + rs.getInt(1));
System.out.println("First Name:" + rs.getString(2));
System.out.println("Last Name:" + rs.getString("lastname"));
System.out.println("Email:" + rs.getString("email"));
System.out.println("BirthDate:" + rs.getDate("birthdate"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
ps.close();
con.close();
}
}
}
了解执行步骤:
步骤1:加载JDBC驱动程序。
Class.forName(" com.mysql.jdbc.Driver")将jdbc驱动程序加载到内存中。
步骤2:现在我们需要获取Connection对象。
下一行将执行此操作。
DriverManager.getConnection(" << JDBC Url >>"," << Db用户名>>"," << db密码>>");
步骤3:我们可以从Connection对象获取PreparedStatement的实例。
我们还需要指定要执行的查询。
例如
PreparedSatement ps = con.prepareStatement(<<查询>>);
PreparedStatement还支持参数化查询。
"?"是查询中的参数。
在执行查询之前,需要提供此参数的值。
步骤4:提供查询参数的值。
上面的示例中只有一个参数,即整数类型的id。
int customerId = 1; ps.setInt(1,customerId); setInt(<<参数编号>>,<<参数值>)方法有2个参数。
在上面的示例中," 1"是参数编号,变量customerId是Parameter的值。
步骤5:执行查询。
PreparedStatement的executeQuery()方法用于执行选择查询。
它将返回ResultSet的实例。
如果查询用于插入,更新或者删除,则可以使用executeUpdate()。
步骤6:迭代ResultSet。
ResultSet的next()方法用于获取查询输出。
步骤7:关闭资源:这是重要的步骤之一。
许多开发人员忘记关闭诸如ResultSet,PreparedStatement和Connection之类的资源。
这将导致资源泄漏,这可能会使您的应用程序崩溃。
程序输出:
Id:1 First Name:Ricky Last Name:Smith Email:[email protected] BirthDate:2001-12-1
1.使用PreparedStatement获取数据
在此示例中,我们将使用PreparedStatement在tblcustomer表中执行插入操作。
package com.theitroad.examples;
import java.sql.*;
import java.text.SimpleDateFormat;
public class PrepareStatementInsertDemo {
public static void main(String[] args) throws Exception {
{
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
String firstname = "matthew";
String lastname = "wade";
String email = "[email protected]";
Date birthdate = new Date(new SimpleDateFormat("YYYY-MM-DD").parse("2000-12-12").getTime());
String query = "insert into tblcustomer (id,firstname,lastname,email,birthdate) values(default,?,?,?,?)";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/customerdb", "root", "root");
ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, firstname);
ps.setString(2, lastname);
ps.setString(3, email);
ps.setDate(4, birthdate);
int row = ps.executeUpdate();
System.out.println("No. of Rows inserted:" + row);
rs = ps.getGeneratedKeys();
if (rs.next()) {
System.out.println("Id of new Customer:" + rs.getInt(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
ps.close();
con.close();
}
}
}
}
在此示例中,在创建PreparedStatement实例时,我们传递了2个参数。
第一个是查询本身,第二个是" Statement.RETURN_GENERATED_KEYS",这将帮助我们获取新行的主键值。
以下代码用于提供用于插入查询的参数。
ps.setString(1, firstname); ps.setString(2, lastname); ps.setString(3, email); ps.setDate(4, birthdate);
如前一个程序所述,executeUpdate()方法用于执行插入操作。
它将返回受我们的查询影响的行数。
程序输出:
No. of Rows inserted:1 Id of new Customer:2
如果转到DB并执行选择查询,则将看到以下结果。
mysql> use customerdb; Database changed mysql> select * from tblcustomer; +----+-----------+----------+------------------+---------------------+ | id | firstname | lastname | email | birthdate | +----+-----------+----------+------------------+---------------------+ | 1 | Ricky | Smith | [email protected] | 2001-12-10 00:00:00 | | 2 | matthew | wade | [email protected] | 1999-12-26 00:00:00 | +----+-----------+----------+------------------+---------------------+ 2 rows in set (0.00 sec)
2.使用PreparedStatement插入操作
现在我们将执行更新操作。
我们将更新电子邮件为" [email protected]"的客户的名字和姓氏。
在上一个示例中插入了该行。
package com.theitroad.examples;
import java.sql.*;
public class PrepareStatementUpdateDemo {
public static void main(String[] args) throws Exception {
{
Connection con = null;
PreparedStatement ps = null;
String email = "[email protected]";
String newFirstname = "john";
String newLastname = "smith";
String query = "update tblcustomer set firstname = ?,lastname =? where email = ?";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/customerdb", "root", "root");
ps = con.prepareStatement(query);
ps.setString(1, newFirstname);
ps.setString(2, newLastname);
ps.setString(3, email);
int row = ps.executeUpdate();
System.out.println("No. of Rows Updated:" + row);
if (row == 1) {
String selectQuery = "select id,firstname,lastname,email,birthdate from tblcustomer where email=?";
try (PreparedStatement selStatement = con.prepareStatement(selectQuery);
) {
selStatement.setString(1, email);
ResultSet rs = selStatement.executeQuery();
if (rs.next()) {
System.out.println("Id:" + rs.getInt(1));
System.out.println("First Name:" + rs.getString(2));
System.out.println("Last Name:" + rs.getString("lastname"));
System.out.println("Email:" + rs.getString("email"));
System.out.println("BirthDate:" + rs.getDate("birthdate"));
}
rs.close();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
ps.close();
con.close();
}
}
}
}
了解程序:
在上面的示例中,我们在查询中有3个参数。
第一个是新的名字,第二个是新的姓氏,第三个是客户的电子邮件。
下面的代码行将此参数的值提供给PreparedStatement。
ps.setString(1, newFirstname); ps.setString(2, newLastname); ps.setString(3, email);
executeUpdate()方法用于执行更新查询。
它将返回查询更新的行数。
程序输出:
No. of Rows Updated:1 Id:2 First Name:john Last Name:smith Email:[email protected] BirthDate:1999-12-26
您可以使用SQL查询在数据库中检查更新。
mysql> select * from tblcustomer; +----+-----------+----------+------------------+---------------------+ | id | firstname | lastname | email | birthdate | +----+-----------+----------+------------------+---------------------+ | 1 | Ricky | Smith | [email protected] | 2001-12-10 00:00:00 | | 2 | john | smith | [email protected] | 1999-12-26 00:00:00 | +----+-----------+----------+------------------+---------------------+ 2 rows in set (0.00 sec)
3.使用PreparedStatement更新操作
现在,我们将删除电子邮件为" [email protected]"的客户记录。
package com.theitroad.examples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class PrepareStatementDeleteDemo {
public static void main(String[] args) throws Exception {
{
Connection con = null;
PreparedStatement ps = null;
String email = "[email protected]";
String query = "delete from tblcustomer where email = ?";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/customerdb", "root", "root");
ps = con.prepareStatement(query);
ps.setString(1, email);
int row = ps.executeUpdate();
System.out.println("No. of Rows Deleted:" + row);
} catch (Exception e) {
e.printStackTrace();
} finally {
ps.close();
con.close();
}
}
}
}
4.使用PreparedStatement删除操作
int executeUpdate():此方法用于执行插入,删除和更新查询。
它将返回一个整数值,指示受查询影响的数字数据库行。void setInt(int parameterIndex,int value):此方法将Integer值设置为指定的参数索引。
PreparedStatement中的批处理方法
package com.theitroad.examples;
import java.sql.*;
import java.text.SimpleDateFormat;
public class PrepareStatementBatchDemo {
public static void main(String[] args) throws Exception {
{
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD");
String query = "insert into tblcustomer (id,firstname,lastname,email,birthdate) values(default,?,?,?,?)";
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/customerdb", "root", "root");
ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
//1st Insert
ps.setString(1, "Ross");
ps.setString(2, "Southee");
ps.setString(3, "[email protected]");
ps.setDate(4, new Date(sdf.parse("2000-12-12").getTime()));
ps.addBatch();
//2nd Insert
ps.setString(1, "Mayank");
ps.setString(2, "Kohli");
ps.setString(3, "[email protected]");
ps.setDate(4, new Date(sdf.parse("2005-12-12").getTime()));
ps.addBatch();
//3rd Insert
ps.setString(1, "Tom");
ps.setString(2, "Patel");
ps.setString(3, "[email protected]");
ps.setDate(4, new Date(sdf.parse("1995-12-12").getTime()));
ps.addBatch();
//Execution
int[] rows = ps.executeBatch();
for (int row : rows) {
System.out.println("No. of Rows inserted:" + row);
}
rs = ps.getGeneratedKeys();
while (rs.next()) {
System.out.println("Id of new Customer:" + rs.getInt(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
ps.close();
con.close();
}
}
}
}
在上面的示例中,我们分批插入了3个客户记录。
批量插入多行而不是单行更为有效。
addBatch()方法可批量添加数据。
executeBatch()执行批处理中的所有查询。
输出:
No. of Rows inserted:1 No. of Rows inserted:1 No. of Rows inserted:1 Id of new Customer:10 Id of new Customer:11 Id of new Customer:12

