在前面的课程中,对SQL语句并没有做预处理工作,而是直接把SQL语句提交给了数据库引擎(执行数据库的核心操作),数据库引擎负责把SQL语句转换为可执行的一系列数据库操作命令,然后执行命令,完成相关的数据库操作。如果大量并发的线程同时提交SQL语句给数据库引擎,这显然让数据库引擎吃不消,就会影响数据库执行的速度,甚至会导致数据库崩溃。
JDBC的PreparedStatement接口可以对SQL语句进行预处理(对SQL语句进行预编译),SQL语句的预处理操作就是把数据库引擎解释SQL语句的任务放在客户端执行,提交给数据库引擎的是已经生成的数据库操作命令,这样就提高了数据库的工作效率。
PreparedStatement接口继承了Statement接口,在Statement接口基础上增加了新的方法,新增加的常用方法说明如下:
boolean execute()
该方法执行此PreparedStatement对象中的SQL语句,该对象可以是任何类型的SQL语句。
ResultSet executeQuery()
该方法执行此PreparedStatement对象中的SQL查询并返回查询生成的ResultSet对象。
int executeUpdate()
该方法执行此PreparedStatement对象中的SQL语句,该对象必须是SQL数据操作语言(DML)语句,如INSERT、UPDATE或DELETE;或者是不返回任何内容的SQL语句,如DDL语句。
void setDate(int parameterIndex, Date x)
该方法将指定的日期对象写入数据库日期字段中。参数parameterIndex表示字段所在记录的列号。参数x为java.sql.Date类型。
void setInt(int parameterIndex, int x)
该方法将指定的int类型的值写入数据库int类型的字段中。参数parameterIndex表示字段所在记录的列号。参数x为int类型。
void setDouble(int parameterIndex, double x)
该方法将指定的double类型的值写入数据库double类型的字段中。参数parameterIndex表示字段所在记录的列号。参数x为double类型。
void setString(int parameterIndex, String x)
该方法将指定的String类型的值写入数据库字符串类型的字段中。参数parameterIndex表示字段所在记录的列号。参数x为String类型。
void setFloat(int parameterIndex, float x)
该方法将指定的float类型的值写入数据库float类型的字段中。参数parameterIndex表示字段所在记录的列号。参数x为float类型。
void addBatch()
该方法将SQL更新语句的一组参数添加到此PreparedStatement对象,对SQL更新语句涉及的表中记录进行批量更新。
Connection接口的prepareStatement ()方法可以返回PreparedStatement对象,具体说明如下:
PreparedStatement prepareStatement(String sql)
该方法创建PreparedStatement对象,用于将编译过的SQL语句发送到数据库。
SQL语句可以预编译并存储在PreparedStatement对象中。然后可以使用此对象多次有效地执行此语句。
案例1:查询shoper表的所有记录,并将记录内容输出到控制台。使用PreparedStatement对象执行SQL语句。
在demo包下新建SqlDemoTest6类。代码如下:
package demo;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* @ClassName: SqlDemoTest6
* @Description: 数据库编程(SQL语句预处理操作)案例1
* @author 编程训练营
* @date
*
*/
public class SqlDemoTest6 {
// 定义JDBC加载路径
static String jdbc = "com.mysql.cj.jdbc.Driver";
// 定义MySQL数据库的连接地址
static String mysqlurl = "jdbc:mysql://localhost:3306/shop?serverTimezone=GMT%2B8";
// 定义MySQL数据库的用户名
static String username = "root";
// 定义MySQL数据库的用户名登录密码
static String password = "~123456q";
/**
* @Title: main
* @Description: Java程序入口main方法
* @param @param args 参数
*
* @return void 返回类型 @throws
*/
public static void main(String[] args) {
Connection conn = null;
PreparedStatement prepareStatement = null;
try {
// 加载JDBC驱动
Class.forName(jdbc);
// 连接数据库
conn = DriverManager.getConnection(mysqlurl, username, password);
if (null != conn) {
System.out.println(conn);
// 获取表记录数的SQL语句
String sql = "select * from shoper";
// 实例化Statement对象
prepareStatement = conn.prepareStatement(sql);
// 执行SQL查询语句
ResultSet resultset = prepareStatement.executeQuery(sql);
if (null != resultset) {
while( resultset.next() )
{
// 获取id字段内容
String id = resultset.getString("id");
// 获取userId字段内容
String userId = resultset.getString("userId");
// 获取name字段内容
String name = resultset.getString("name");
// 获取brief字段内容
String brief = resultset.getString("brief");
// 获取log字段内容
String log = resultset.getString("log");
// 获取shopMoney字段内容
BigDecimal shopMoney = resultset.getBigDecimal("shopMoney");
// 获取status字段内容
int status = resultset.getInt("status");
// 获取createDate字段内容
Date createDate = resultset.getDate("createDate");
System.out.printf("-----输出第%d条记录-----\n",resultset.getRow());
System.out.println("id:" + id + ";");
System.out.println("userId:" + userId + ";");
System.out.println("name:" + name + ";");
System.out.println("brief:" + brief + ";");
System.out.println("log:" + log + ";");
System.out.println("shopMoney:" + shopMoney.toString() + ";");
System.out.println("status:" + status + ";");
System.out.println("createDate:" + createDate.toString() + ";");
System.out.println("-------------------------------");
}
resultset.close();
} else {
System.out.println("SQL语句执行失败");
}
prepareStatement.close();
conn.close();
} else {
System.out.println("数据库连接失败");
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}SqlDemoTest6程序代码和SqlDemoTest2程序代码基本相同,主要区别是PreparedStatement接口替代了Statement接口,conn对象调用的是prepareStatement()方法,而不是createStatement()方法。
程序执行结果如下图所示:
