JDBC不仅可以执行数据库查询,还可以执行DDL、DML等SQL语句,以便最大限度地操作数据库。
execute()方法
Statement接口的execute()方法几乎可以执行任何SQL语句,如果不清楚SQL语句的类型,则只能通过使用execute()方法来执行SQL语句。
使用execute()方法执行SQL语句的返回值是boolean值,表明执行该SQL语句是否返回了ResultSet对象:
● 当返回值为true时,可以使用Statement的getResultSet()方法,来获取execute()方法执行SQL查询语句所返回的ResultSet对象;
● 当返回值为false时,可以使用getUpdateCount()方法,来获取execute()方法执行DML语句所影响的行数。
下述案例示例了Statement对象的execute()方法的使用,代码如下所示。
【代码14.3】
ExecuteExample.java
package com;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ExecuteExample {
private String driver = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://127.0.0.1:3306/student";
private String user = "root";
private String pass = "root";
public void executeSql(String sql) throws Exception {
// 加载驱动
Class.forName(driver);
try (
// 获取数据库连接
Connection conn = DriverManager.getConnection(url, user, pass);
// 使用Connection来创建一个Statement对象
Statement stmt = conn.createStatement()) {
// 执行SQL,返回boolean值表示是否包含ResultSet
boolean hasResultSet = stmt.execute(sql);
// 如果执行后有ResultSet结果集
if (hasResultSet) {
try (
// 获取结果集
ResultSet rs = stmt.getResultSet()) {
// 迭代输出ResultSet对象
while (rs.next()) {
// 依次输出第1列的值
System.out.print(rs.getString(1) + "\t");
}
System.out.println();
}
} else {
System.out.println("该SQL语句影响的记录有"
+ stmt.getUpdateCount() + "条");
}
}
}
public static void main(String[] args) throws Exception {
ExecuteExample executeObj = new ExecuteExample();
System.out.println("------执行建表的DDL语句-----");
executeObj.executeSql("create table my_test" +
"(test_id int primary key, test_name varchar(25))");
System.out.println("------执行插入数据的DML语句-----");
executeObj.executeSql("insert into my_test(test_id,test_name) "
+ "select id,name from t_user");
System.out.println("------执行查询数据的查询语句-----");
executeObj.executeSql("select test_name from my_test");
System.out.println("------执行删除表的DDL语句-----");
executeObj.executeSql("drop table my_test");
}
}
上述代码先定义了一个executeSql()方法,用于执行不同的SQL语句,当执行结果有ResultSet结果集时,则循环输出结果集中第3列的信息;否则输出该SQL语句所影响的记录条数。在main()方法中,调用executeSql()方法,分别执行建表、插入、查询和删除表四个SQL语句。程序运行结果如下:
------执行建表的DDL语句-----
该SQL语句影响的记录有0条
------执行插入数据的DML语句-----
该SQL语句影响的记录有2条
------执行查询数据的查询语句-----
向守超 张恒
------执行删除表的DDL语句-----
该SQL语句影响的记录有0条
需要注意的是:使用Statement执行DDL和DML语句的步骤与执行普通查询语句的步骤基本相似。区别在于执行DDL语句后返回值为0,而执行了DML语句后返回值为受影响的行数。
executeUpdate()方法
executeUpdate()和executeLargeUpdate()方法用于执行DDL和DML语句,其中executeLargeUpdate()方法是Java 8新增的方法,是增强版的executeUpdate()方法。executeLargeUpdate()方法的返回值类型为long,当DML语句影响的记录超过Integer.MAX_VALUE时,建议使用该方法。
下述案例示例了Statement对象的executeUpdate()方法的使用,目前MySQL数据库驱动暂不支持executeLargeUpdate()方法功能。代码如下所示。
【代码14.4】
ExecuteUpdateExample.java
package com;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class ExecuteUpdateExample {
private String driver = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://127.0.0.1:3306/student";
private String user = "root";
private String pass = "root";
public void createTable(String sql) throws Exception {
// 加载驱动
Class.forName(driver);
try (
// 获取数据库连接
Connection conn = DriverManager.getConnection(url, user, pass);
// 使用Connection来创建一个Statment对象
Statement stmt = conn.createStatement()) {
// 执行DDL,创建数据表
stmt.executeUpdate(sql);
}
}
public long insertData(String sql) throws Exception {
// 加载驱动
Class.forName(driver);
try (
// 获取数据库连接
Connection conn = DriverManager.getConnection(url, user, pass);
// 使用Connection来创建一个Statment对象
Statement stmt = conn.createStatement()) {
// 执行DML,返回受影响的记录条数
return stmt.executeUpdate(sql);
}
}
public static void main(String[] args) throws Exception {
ExecuteUpdateExample elud = new ExecuteUpdateExample();
elud.createTable("create table my_test1" +
"(test_id int primary key, test_name varchar(25))");
System.out.println("-----建表成功-----");
long result = elud.insertData(
"insert into my_test1(test_id,test_name) select id,name from t_user");
System.out.println("--系统中共有" + result + "条记录受影响--");
}
}
上述代码定义了createTable()方法来创建表,insertData()方法用于插入数据,不管是执行DDL语句还是执行DML语句,最终都是通过调用Statement对象的executeUpdate()方法来实现的。运行该程序,结果如下所示:
-----建表成功-----
–系统中共有2条记录受影响–
PreparedStatement接口
PreparedStatement接口继承Statement接口,该接口具有以下两个特点:
● PreparedStatement对象中所包含的SQL语句将进行预编译,当需要多次执行同一条SQL语句时,直接执行预先编译好的语句,其执行速度比Statement对象快;
● PreparedStatement可用于执行动态的SQL语句,即在SQL语句中提供参数,大大提高了程序的灵活性和执行效率。
动态SQL语句使用“?”作为动态参数的占位符,示例如下所示。
例如:参数化的动态SQL语句,创建PreparedStatement对象
String insertSql = "INSERT INTO userdetails(sid,name,password,sex) VALUES(?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(insertSql);
在执行带参数的SQL语句前,必须对“?”占位符参数进行赋值。PreparedStatement接口中提供了大量的setXXX()方法,通过占位符的索引完成对输入参数的赋值,根据参数的类型来选择对应的setXXX()方法,PreparedStatement接口中提供的常用setXXX()方法如表14-7所示。
下述案例示例了PreparedStatement的使用,代码如下所示。
【代码14.5】PreparedStatementExample.java
package com;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class PreparedStatementExample {
public static void main(String[] args) {
try {
// 加载oracle驱动
Class.forName("com.mysql.jdbc.Driver");
// 建立数据库连接
Connection conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/student", "root", "root");
// 定义带参数的sql语句
String insertSql = "INSERT INTO t_user(sid,name,password,sex)"
+ " VALUES(?,?,?,?)";
// 创建PreparedStatement对象
PreparedStatement pstmt = conn.prepareStatement(insertSql);
// 使用setXXX()方法对参数赋值
pstmt.setInt(1, 7);
pstmt.setString(2, "Tom");
pstmt.setString(3, "123456");
pstmt.setByte(4, (byte) 1);
// 执行
int result = pstmt.executeUpdate();
System.out.println("插入" + result + "行!");
// 关闭载体
pstmt.close();
// 关闭连接
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
上述代码先定义一个带参数的SQL语句;再使用该语句来创建一个PreparedStatement对象;然后调用PreparedStatement对象的setXXX()方法对参数进行赋值,并调用PreparedStatement对象的executeUpdate()方法来执行SQL语句。运行该程序,结果如下所示:
插入1行!
我是田先生,一名热爱技术、热爱生活的Java程序员。专注分享java基础、dubbo源码、zookeeper, rabbitmq、mybatis源码、微服务springboot、集群、分布式、多线程等相关知识与实战经验。欢迎大家积极交流,共同探讨。欢迎关注我的公众号:t-j20120622(Java后端技术栈)。