Statement, PreparedStatement, CallableStatement

一旦建立好连接, 就可以与数据库交互. JDBC 中Statement, PreparedStatement 和 CallableStatement 提供了SQL操作的相关API. 其中 CallableStatement 继承自 PreparedStatement, 而 PreparedStatement 又继承自 Statement. 他们的区别是:

Statement 提供基本的 SQL 操作. 适合静态SQL语句, 且传入的 SQL 语句无法接受参数.

PreparedStatement 可以在 SQL 中传递参数, 适合多次使用的 SQL 语句.

CallableStatement 可以调用 PL/SQL 存储过程.

尽管接口功能有不同, 但是使用方式大体相同, 分以下几步:

创建 Statement

执行 SQL 语句

关闭 Statement

在执行 SQL 语句的时候, 常用以下几个方法:

boolean execute(String SQL) : 如果有 ResultSet 产生返回true, 否则, 返回 false. 一般用于 CREATE, ALTER 这些操作, 或者用来检查一个Query有没有返回.

int executeUpdate(String SQL) : 返回被影响的记录的条数, 一般用于 INSERT, UPDATE, DELETE 这些操作.

ResultSet executeQuery(String SQL) : 返回查询结果集, 专用语 SELECT.

以下三个例子分别示例了如何适用他们.

Statement 例子.

public class StatementExample {

private Properties dbProps = new Properties();

StatementExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public void deleteAll() throws SQLException {

String sql = "DELETE FROM posts";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

int nRows = stmt.executeUpdate(sql);

System.out.println(nRows + (nRows == 1 ? " post is " : " posts are ") + "deleted.");

stmt.close();

conn.close();

}

public void insertPost(Post post) throws SQLException {

String sql = "INSERT INTO posts VALUES";

String title = post.getTitle();

String content = post.getContent();

Boolean visible = post.isVisible();

sql += "("

+ "NULL" + ","

+ "\"" +title + "\"" + ","

+ "\"" + content + "\"" + ","

+ "DEFAULT" + ","

+ (visible ? "TRUE" : "FALSE")

+ ")";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

int nRows = stmt.executeUpdate(sql);

stmt.close();

conn.close();

}

public ArrayList<Post> queryAll() throws SQLException {

ArrayList<Post> list = new ArrayList<Post>();

String sql = "SELECT * FROM posts";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery(sql);

rs.beforeFirst();

while (rs.next()) {

Post temp = new Post();

temp.setId(rs.getInt("id"));

temp.setTitle(rs.getString("title"));

temp.setContent(rs.getString("content"));

temp.setDate(rs.getTimestamp("dt_create"));

temp.setVisible(rs.getBoolean("visible"));

list.add(temp);

}

stmt.close();

conn.close();

return list;

}

public static void main(String[] args) {

try {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

StatementExample example = new StatementExample();

example.setDBProperties(props);

ArrayList<Post> posts = example.queryAll();

System.out.println(posts);

Post toInsert = new Post();

toInsert.setTitle("new Post");

toInsert.setContent("This is a new post!");

example.insertPost(toInsert);

posts = example.queryAll();

System.out.println(posts);

example.deleteAll();

posts = example.queryAll();

System.out.println(posts);

} catch (SQLException e) {

DBUtils.printSQLException(e);

} catch (Exception e) {

e.printStackTrace();

}

}

}

PreparedStatement 例子.

public class PreparedStatExample {

private Properties dbProps = new Properties();

PreparedStatExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public void deletePost(int id) throws SQLException {

String sql = "DELETE FROM posts WHERE id = ?";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setInt(1, id);

stmt.executeUpdate();

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

public void insertPost(Post post) throws SQLException {

String sql = "INSERT INTO posts VALUES(NULL, ?, ?, DEFAULT, ?)";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setString(1, post.getTitle());

stmt.setString(2, post.getContent());

stmt.setBoolean(3, post.isVisible());

stmt.executeUpdate();

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

public ArrayList<Post> queryByTitle(String title) throws SQLException {

ArrayList<Post> list = new ArrayList<Post>();

String sql = "SELECT * FROM posts WHERE title like ?";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setString(1, title);

ResultSet rs = stmt.executeQuery();

rs.beforeFirst();

while (rs.next()) {

Post temp = new Post();

temp.setId(rs.getInt("id"));

temp.setTitle(rs.getString("title"));

temp.setContent(rs.getString("content"));

temp.setDate(rs.getTimestamp("dt_create"));

temp.setVisible(rs.getBoolean("visible"));

list.add(temp);

}

stmt.close();

conn.close();

return list;

}

public static void main(String[] args) {

try {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

PreparedStatExample example = new PreparedStatExample();

example.setDBProperties(props);

// 此时数据库中有一条 title 为 111 的数据

ArrayList<Post> posts = example.queryByTitle("111");

System.out.println(posts); //[Post{id=34, title='111', content='111', date=2015-01-25 12:58:32.0, visible=true}]

Post toInsert = new Post();

toInsert.setTitle("111");

toInsert.setContent("111111");

example.insertPost(toInsert);

posts = example.queryByTitle("111");

System.out.println(posts); // [Post{id=39, title='111', content='111', date=2015-01-25 13:00:49.0, visible=true}, Post{id=41, title='111', content='111111', date=2015-01-25 13:00:59.0, visible=false}]

example.deletePost(posts.get(0).getId());

posts = example.queryByTitle("111");

System.out.println(posts); // [Post{id=41, title='111', content='111111', date=2015-01-25 13:00:59.0, visible=false}]

} catch (SQLException e) {

DBUtils.printSQLException(e);

} catch (Exception e) {

e.printStackTrace();

}

}

}

CallableStatement 例子.

public class CallableStatExample {

private Properties dbProps = new Properties();

public CallableStatExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public String getTitleById(int id) throws SQLException {

Connection conn = getConnection();

String sql = "{call getTitleById (?, ?)}";

CallableStatement stmt = conn.prepareCall(sql);

// 绑定传入参数

stmt.setInt(1, id);

// 对于传出参数, 要先注册

stmt.registerOutParameter(2, java.sql.Types.VARCHAR);

stmt.execute();

String title = stmt.getString(2);

stmt.close();

conn.close();

return title;

}

public static void main(String[] args) throws IOException, SQLException {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

CallableStatExample example = new CallableStatExample();

example.setDBProperties(props);

int id = 35;

String title = example.getTitleById(id);

System.out.println("Find title : " + title + " by ID : " + id); // Find title : 222 by ID : 35

}

}

Note: 请先将以下存储过程存入 MySQL 数据库

DELIMITER $$

CREATE PROCEDURE `testdb`.`getTitleById`

(IN post_id INT, OUT post_name VARCHAR(255))

BEGIN

SELECT title INTO post_name

FROM posts

WHERE ID = post_id;

END $$

DELIMITER ;

SQL 的批处理操作

SQL 批处理能够允许添加多个 SQL 到 一个Statement对象, 并一并提交执行结果. 这减少了与 SQL 通信的频率. 但是, SQL 批处理不是 JDBC 要求一定要支持的. 使用前应该用 DatabaseMetaData.supportsBatchUpdates() 检查支持情况.

SQL 批处理相关的 API 有:

Statement.addBatch(): 往批处理中添加 SQL 语句

Statement.executeBatch(): 执行批处理, 并返回一个整型数组, 其中每个元素代表对应序号 SQL 的执行结果.

Statement.clearBatch(): 从批处理中删除已添加的所有 SQL 语句.

以下示例如何使用批处理往数据库添加数据:

public static void batchInsertPosts(ArrayList posts) throws SQLException {

Connection conn = getConnectionFromDS(dbProps);

conn.setAutoCommit(false); // 见 "事务" 一章

DatabaseMetaData md = conn.getMetaData();

System.out.println("If support batch updates: " + md.supportsBatchUpdates());

String sql = "INSERT INTO POSTS\n"

+ "VALUES(NULL, ?, ?, DEFAULT, ?)";

PreparedStatement stmt = conn.prepareCall(sql);

try {

for (Post post : posts) {

stmt.setString(1, post.getTitle());

stmt.setString(2, post.getContent());

stmt.setBoolean(3, post.isVisible());

stmt.addBatch();

}

stmt.executeBatch();

conn.commit();

} catch (SQLException e) {

DBUtils.printSQLException(e);

conn.rollback();

}

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

SQL 异常处理

JDBC 中最常用的异常就是 SQLException, 不管是在建立连接, 还是在执行 SQL 语句的时候, 都有可能抛出这个异常. SQLException 包含以下信息:

关于错误的描述. 通过调用getMessage() 获得.

一个 SQL 状态码. 通过调用 getSQLState( ) 获取. SQL 状态码由5位字母和数字组成, 符合 XOPEN 规范.

一个错误码. 这个错误码的含义由实现规定, 有可能是数据库的错误码. 通过调用 SQLException.getErrorCode() 获取.

错误缘由. 引发异常的缘由, 有可能是一个或者多个 Throwable 的对象组成的一条链. 要想检查这些缘由, 要递归遍历 SQLException.getCause() 直到返回一个 null.

异常链. 通过 getNextException() 获取下一个异常.

以下代码示例如何打印异常链中的每个SQLException异常, 并且打印每个异常的 cause 链.

public static void printSQLException(SQLException ex) {

for (Throwable e : ex) { // Iterator 会调用 getNextException()

if (e instanceof SQLException) {

e.printStackTrace(System.err);

System.err.println("SQLState: " +

((SQLException)e).getSQLState());

System.err.println("Error Code: " +

((SQLException)e).getErrorCode());

System.err.println("Message: " + e.getMessage());

Throwable t = ex.getCause();

while(t != null) { // 打印每个 cause

System.out.println("Cause: " + t);

t = t.getCause();

}

}

}

}

除了发生致命错误产生抛出 SQLException 之外, Connection, Statement, ResultSet 都有一个 getWarnings() 方法, 它返回一个 SQLWarning. SQLWarning 继承自 SQLException, 可以向遍历 SQLException 一样遍历它:

public static void printWarnings(SQLWarning warning)

throws SQLException {

while (warning != null) {

System.out.println("Message: " + warning.getMessage());

System.out.println("SQLState: " + warning.getSQLState());

System.out.print("Vendor error code: ");

System.out.println(warning.getErrorCode());

System.out.println("");

warning = warning.getNextWarning();

}

}

mysql中statement_Statement (操作 SQL 语句)相关推荐

  1. mysql 如何优化sql语句,如何优化SQL?MySQL中超实用的SQL语句送给大家

    如何优化SQL?MySQL中超实用的SQL语句送给大家 如何优化SQL?MySQL中超实用的SQL语句送给大家 在写SQL时,经常灵活运用一些SQL语句编写的技巧,可以大大简化程序逻辑.减少程序与数据 ...

  2. ​MYSQL中常用的SQL语句​(增删改查)

    MYSQL中常用的SQL语句 一.增删改查 1.新增 指定字段插入: INSERT INTO <表名> (<字段1>, <字段2>, <字段3>) VA ...

  3. 在mysql中更新数据sql语句怎么写_在MySQL中,更新数据库表记录的SQL语句,包括______语句...

    在MySQL中,更新数据库表记录的SQL语句,包括______语句 答:insert replace update delete 在域F中,设其特征为2,对于任意a,b∈F,则(a+b)2 等于多少 ...

  4. mysql中dist_在SQL语句中dist是什么意思

    展开全部 dist是 distinct 的缩写,意思是在查询结果中62616964757a686964616fe4b893e5b19e31333431363032去掉重复的记录. 使用distinct ...

  5. mysql in语句 索引,MySQL 中索引相关 SQL 语句

    索引是用来加快从数据库中查询数据的速度的. 需要注意的是索引的使用会增加插入和更新的时间,因为在插入数据的同时也会更新索引.所以在创建索引时确保只在那些频繁作为查询条件的列中增加. 创建索引 创建索引 ...

  6. MySQL中如何使用SQL语句创建、管理索引

    目录 #

  7. 执行计划 分析一条sql语句的效率 mysql_MySQL中一条SQL语句的执行过程

    MySQL中一条SQL语句的执行过程 发布时间:2018-11-24 18:35, 浏览次数:390 , 标签: MySQL SQL 查询语句的执行顺序: 1.客户端通过TCP连接发送连接请求到mys ...

  8. oracle 查看用户日志,Oracle查看用户操作sql语句以及数据库日志

    --查看日志文件 select member from v$logfile; --查看表空间使用情况 SELECT SUM(bytes) / (1024 * 1024) AS free_space, ...

  9. MySQL数据库https接口_第三章 mysql 数据库接口程序以及SQL语句操作

    mysql  数据库接口程序以及SQL语句操作 用于管理数据库: 命令接口自带命令 DDL:数据定义语言(create drop ) DCL: 数据控制语言(grant revoke) DML: 数据 ...

最新文章

  1. apn java_android设置移动联通电信wap接入点
  2. 图像修复中的TV模型
  3. 06.系统编程-2.线程
  4. 深蓝学院《从零开始手写VIO》作业五
  5. wampserver2.5安装 redis缓存,igbinary, phalcon框架
  6. 直播 | 清华大学李一鸣:后门攻击简介
  7. v8学习笔记(八) 【JS与C++互调】
  8. 字节前端终于开源!吹爆!
  9. FreeRTOS信号量---二值信号量
  10. 斐波那契数列 (C#)
  11. android datepicker 参数设置,如何在Android DatePicker中设置最小和最大日期?
  12. android 生命周期流程图,Android Studio ——Service的生命周期
  13. idea一键导包快捷键_十三肝了2晚的《IDEA操作手册-终极秘籍》终于来了...
  14. 【Erlang开源项目】HTTP客户端ibrowse
  15. 第一阶段✦第一章☞信息化知识
  16. Weka的全名是怀卡托智能分析环境
  17. BLE service, characteristic以及CCCD概念 9
  18. 贼有趣:朱茵变杨幂,人工智能换脸让明星不再担心自己演技?
  19. 青花瓷音乐的单片机c语言程序,c语言曲谱_单片机c语言音乐简谱代码
  20. 买保险选大公司还是小公司?

热门文章

  1. ubuntu美化终端
  2. python数据分析与挖掘实践大作业_数据挖掘大作业最终报告.PDF
  3. python 实现三维平面拟合 附纸质版最小二乘法的推导与程序的实现
  4. EasyExcel对Excel文件的解析过程
  5. 中缀 转 后缀 实现计算
  6. oracle数据库ora00942,ORA-00604 ORA-00942问题处理
  7. SpringBoot系列教材 (十三)- 持久层支持 - springboot中如何运用JPA,简单例子
  8. 北京个人ADSL和企业ADSL有什么区别啊?
  9. python绘制小提琴图片_手把手教你用 Origin 绘制小提琴图
  10. 类型推导decltype