java.sql.Statement 接口,是专门用来执行sql语句的,该接口还有俩个子接口:
java.sql.PreparedStatementjava.sql.CallableStatement它们的关系如下:
CallableStatement 接口继承了 PreparedStatement 接口PreparedStatement 接口又继承了 Statement 接口PreparedStatement 接口,简称PS,它除了拥有 Statement 的功能特点之外,它还有有着自己的特点:可以对sql语句进行预处理。
Statement是每次执行一个sql语句,就要把一个完成的sql语句发送给数据库进行执行,然后取回返回的结果。
PreparedStatement可以把一个sql语句的结构,提前发送给数据库进行预处理,然后在专门给发送要操作的具体的值,在数据量大的时候,这种方式会大大提高执行效率。
例如,使用stmt和ps分别向表中插入10000条数据,观察使用时间
package com.briup.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; //可以使用序列 //drop sequence user_seq; //create sequence user_seq; public class PSTest { private String driverClass = "oracle.jdbc.driver.OracleDriver"; private String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE"; private String user = "briup"; private String password = "briup"; @Test public void stmt() { Connection conn = null; Statement stmt = null; try { //1.加载注册驱动 Class.forName(driverClass); //2.获取连接对象 conn = DriverManager.getConnection(url,user,password); //3.获取Statement对象 stmt = conn.createStatement(); //4.执行SQL语句 String sql = ""; for(int i=1;i<=10000;i++) { sql = "insert into t_user(id,name,age) values(user_seq.nextval,'tom"+i+"',20)"; stmt.executeUpdate(sql); } //5.处理结果 System.out.println("stmt执行结束:"); } catch (Exception e) { e.printStackTrace(); } finally { //6.释放资源 if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } @Test public void ps() { Connection conn = null; PreparedStatement ps = null; try { //1.加载注册驱动 Class.forName(driverClass); //2.获取连接对象 conn = DriverManager.getConnection(url,user,password); //3.获取PS对象 //具体每次不同的数据,可以先用占位符符表示,ps会提前把sql发给数据库预处理,后面 只发送数据 String sql = "insert into t_user(id,name,age) values(user_seq.nextval,?,?)"; ps = conn.prepareStatement(sql); //4.执行SQL语句 for(int i=1;i<=10000;i++) { ps.setString(1, "tom"+i); ps.setInt(2, 20); ps.executeUpdate(); } //5.处理结果 System.out.println("ps执行结束:"); } catch (Exception e) { e.printStackTrace(); } finally { //6.释放资源 if(ps!=null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } private long start; private long end; //测试方法执行之前,该方法执行 @BeforeEach public void start() { start = System.currentTimeMillis(); } //测试方法执行之后,该方法执行 @AfterEach public void end() { end = System.currentTimeMillis(); System.out.println("共耗时"+(end-start)+"毫秒"); System.out.println(); } } //运行结果: ps执行结束: 共耗时3258毫秒 stmt执行结束: 共耗时7050毫秒ps和stmt对比好处:
使用 stmt ,每次都需要,使用字符串拼接出一个完整的sql语句,再发送给数据库,如果sql语句 比较复杂,需要拼接的数据比较多,那么在字符串拼接过程中,就很容易出错误。使用 ps ,就不需要拼接字符串,因为只需要先把带占位符的sql发给数据库,之后在专门发送数据,代替占位符就可以了,这里基本不会出现在sql中拼接字符串的情况。