JDBC Statement、 PreparedStatement、 CallableStatement三者举例与区别
本篇总结JDBC执行SQL语句的三种方式,主要演示向数据表插入一行数据,文中的数据库名为JavaSE,数据表名为tb_user。
我的数据库连接名为“admin”,密码为“xyz123”,这里是自己装SQLServer时自己设置的。
这里给出建立数据库和数据表的SQL语句:
CREATE DATABASE IF NOT EXISTS JavaSE;
USE JavaSE;
CREATE TABLE IF NOT EXISTS tb_user(
user_id INT PRIMARY KEY auto_increment,
user_name VARCHAR(20),
user_age INT,
user_sex VARCHAR(5)
);
执行成功后数据表中没有一条数据,如下:
1.先总结下JDBC连接数据库的步骤
- 加载数据库驱动
- 获取连接
- 创建SQL语句
- 执行SQL语句
- 返回结果集
本文主要总结的是执行SQL语句的三种方式
2.执行SQL语句的三种方式
①Statement 概念不多介绍,直接上代码,相关注释在代码中已注明。实现了向JavaSE数据库下的tb_user表中插入一行数据
import java.sql.*;
public class TestStatement {
private static String driver = "com.mysql.cj.jdbc.Driver";
/*给数据库添加utf-8化,不然不支持中文 serverTimezone=UTC添加当前连接时间戳,useSSL=true 数据库连接证书*/
private static String URL = "jdbc:mysql://localhost:3306/JavaSE?characterEncoding=UTF-8&user=admin&password=xyz123&
serverTimezone=UTC&useSSL=true";
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
try{
Class.forName(driver);
System.out.println("驱动加载成功...");
conn = DriverManager.getConnection(URL);
System.out.println("获取连接成功...");
st = conn.createStatement();//创建执行环境
String sql = "insert into tb_user values(null,'张三丰',20,'男')";
if(st.executeUpdate(sql) > 0){
System.out.println("执行成功...");
} else{
System.out.println("执行失败...");
}
}catch (Exception e){
e.printStackTrace();
}finally {//关闭连接
try{
if (conn != null){
conn.close();
}
if(st != null){
st.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果如下:可见数据已插入数据表中
②PreparedStatement,同样是往tb_user表中插入一条数据
代码如下:
import java.sql.*;
public class TestPrest {
private static String driver = "com.mysql.cj.jdbc.Driver";
/*给数据库添加utf-8化,不然不支持中文 serverTimezone=UTC添加当前连接时间戳, useSSL=true 数据库连接证书*/
private static String URL = "jdbc:mysql://localhost:3306/JavaSE?characterEncoding=UTF-8&user=admin&password=xyz123&serverTimezone=UTC&useSSL=true";
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
try{
Class.forName(driver);
System.out.println("驱动加载成功...");
conn = DriverManager.getConnection(URL);
System.out.println("获取连接成功...");
String sql = "insert into tb_user values(null,?,?,?)";
pst = conn.prepareStatement(sql);
//拼接SQL指令序号占位符的装载过程
pst.setString(1, "王铁军");
pst.setInt(2,25);
pst.setString(3, "男");
//接着执行
if(pst.executeUpdate() > 0){
System.out.println("新增执行成功...");
}else{
System.out.println("新增执行失败...");
}
}catch (Exception e){
e.printStackTrace();
}finally {//关闭连接
try{
if (conn != null){
conn.close();
}
if (pst != null){
pst.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果如下:可见数据表新增了一条数据
③CallableStatement继承了PreparedStatement,除了拥有PreparedStatement的功能外,还扩展了自己的功能,比如支持存储过程的调用,下面的例子就是基于调用存储过程来插入数据的。
首先创建插入语句存储过程,代码如下:
CREATE PROCEDURE insert_(in name VARCHAR(20), in age INT, in sex VARCHAR(5))
BEGIN
INSERT INTO tb_user VALUES(null, name, age, sex);
END;
代码如下:
import com.mysql.cj.jdbc.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
public class TestCallablesmt {
private static String driver = "com.mysql.cj.jdbc.Driver";
private static String URL = "jdbc:mysql://localhost:3306/JavaSE?
characterEncoding=UTF-8&user=admin&password=xyz123&serverTimezone=UTC&useSSL=true";
public static void main(String[] args) {
Connection conn = null;
CallableStatement cst = null;
try{
Class.forName(driver);
System.out.println("驱动加载成功...");
conn = DriverManager.getConnection(URL);
System.out.println("获取连接成功...");
String sql = "{call insert_(?,?,?)}";//存储过程函数
cst = (CallableStatement) conn.prepareCall(sql);
cst.setString(1,"李艳");
cst.setInt(2, 19);
cst.setString(3, "女");
cst.executeUpdate();//执行
System.out.println("执行成功...");
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if (conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
运行结果如下:可见数据表中又新增了一条数据
3.总结
①三种执行方式的创建
- Statement使用createStatement()创建;
- PreParedStatement经过预编译并存储在PreparedStatement对象中的SQL语句,使用prepareStatement()方法创建;
- CallableStatement扩展了存储过程的调用,使用prepareCall()方法创建。
②PreparedStatement与Stateme的比较
- Statement支持静态的SQL语句,而PreparedStatement支持动态的查询参数,即通过使用’?’占位符进行动态参数化查询;
- PreparedStatement对查询语句进行类预编译,下次使用时加载更快,所以查询效率比statement高;
- PreparedStatement可以防止SQL注入式攻击。在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此,就算参数中含有破坏性的指令,也不会被数据库执行。
③CallableStatement
CallableStatement继承了PreparedStatement接口,扩展了调用存储过程的功能。存储过程是在大型数据库系统中,一组为了完成特定功能的SQL语句集,它存储在数据库中,一次编译永久有效,用户可以指定存储过程的名字并给出参数来执行它。存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用好存储过程能够达到倍速的效率提升。
注:如有不对的地方,欢迎大家交流指正。