结构图

数据库程序接口——JDBC——API解读第二篇——执行SQL的核心对象-LMLPHP

核心对象

Statement

Statement主要用来执行SQL语句。它执行SQL语句的步骤为:

  1. 第一步:创建statement对象。
  2. 第二步:配置statement对象,此步骤可以忽略。
  3. 第三步:调用statement的executeXXX方法执行SQL语句。
  4. 第四步:处理结果集。示例中只是打印结果集。
  5. 第五步:关闭statement对象。

Statement执行SQL语句的方法有四种类型。

  1. execute执行返回结果包含一个或者多个结果集,或结果包含一个或多个更新记录数量的SQL语句。返回类型为布尔,当执行SQL语句返回结果为ResultSet对象时为true,其他情形为false。
  2. executeQuery执行返回结果为ResultSet对象的SQL语句,例如select语句。返回类型为ResultSet对象。
  3. executeUpdate执行返回结果为更新记录数量的SQL语句,例如update,Insert,delete语句。它也可以用来DDL语句。返回值类型为int。当执行update,insert,delete语句时,int值表示更新记录数量,其他情形返回0。
  4. executeLargeUpdate方法与executeUpdate方法类似。适用于更新数量较多的情况。返回值类型为Long

创建对象

参考Connection对象

get&set

 /**----------Statement对象相关-----------**/
// 设置支持Pooled
statement.setPoolable(true);
System.out.println("statement语句的是否支持Pooled:" + statement.isPoolable());
System.out.println("statement语句是否已经关闭:" + statement.isClosed());
/**----------SQL执行过程----------**/
// 建议结果集的排序方式,类型有三种,FETCH_FORWARD,FETCH_REVERSE,FETCH_UNKONWN
statement.setFetchDirection(ResultSet.FETCH_REVERSE);
// 建议每一次接收结果集的条数
statement.setFetchSize(10);
// 设置ResultSet最大的条数
statement.setMaxRows(10);
// 设置字段内容最大的字节数
statement.setMaxFieldSize(100);
// 设置执行sql语句的超时时间
statement.setQueryTimeout(1);
// 设置是否执行Escape类型的SQL语法。
statement.setEscapeProcessing(false);
/**-----------结果集相关信息------------**/
System.out.println("statement语句的FetchDirection为:" + statement.getFetchDirection());
System.out.println("statement语句的FetchSize为:" + statement.getFetchSize());
System.out.println("statement语句的maxFieldSize:" + statement.getMaxFieldSize());
System.out.println("statement语句的maxRows为:" + statement.getMaxRows());
System.out.println("statement语句的queryTimeOut为:" + statement.getQueryTimeout());
System.out.println("statement语句的结果集更新方式:" + statement.getResultSetConcurrency());
System.out.println("statement语句的结果集关闭方式:" + statement.getResultSetHoldability());
System.out.println("statement语句的结果集的遍历方式:" + statement.getResultSetType());
System.out.println("statement语句的LargeMaxRows为:" + statement.getLargeMaxRows());

executeSQL

  1. execute(sql):参数sql表示一条sql语句。例如select 1 from dual;select 2 from dual;它包含两条sql语句。这种情形是不允许的
  2. execute(sql,autoGeneratedKeys):参数autoGneratedKeys,TODO
  3. execute(sql,columnIndexs):参数columnIndexs表示列的索引值,从1开始。类型为int数组
  4. execute(sql,columnNames):参数columnNames表示列名称,类型为String数组。

executeUpdate,executeQuery,executeLargeUpdate拥有和execute方法相同的参数和重载方法

批量

  1. addBatch(sql):在批量执行的SQL语句中添加sql语句。参数sql表示一条sql语句。sql语句的类型可以是delete,update,insert的任意一种。执行每条SQL返回值类型为int。如果批量执行其他类型的SQL语句,可以使用存储过程。
  2. executeBatch:批量执行SQL,返回值为int数组。数组的每个值表示每条SQL语句更新记录数量的值
  3. executeLargeBatch:含义与executeBatch相同。返回值类型为Long数组。
  4. clearBatch:清空批量执行的SQL。
  5. cancel:取消正在执行的SQL语句。

示例如下:

 /**
* 演示Statement对象的方法。 本示例中使用到的数据库表为student,该表字段为名称,学号,班级,主修课,
* 本示例中创建Statement调用的方法参考Connection,DriverManager,Driver等对象。
*
*/
public class StatementSample {
public static void main(String[] args) throws SQLException {
// 创建Statement对象
Statement statement = createStatement();
// 使用execute方法执行sql语句
executeSQL(statement);
// 使用executeQuery方法执行sql语句
executeQuerySQL(statement);
// 使用executeUpdate方法执行sql语句
executeUpdateSQL(statement);
} /**
* 创建Statement对象
*
* @return Statement对象
* @throws SQLException
*/
public static Statement createStatement() throws SQLException {
// 创建Connection对象
Connection conn = DataSourceUtil.getConnectionByDriver();
// 创建Statement对象
Statement statement = conn.createStatement();
return statement;
} /**
* 调用Statement对象的execute方法,示例为:select 1 from dual 测试语句
*
* @return ResultSet 结果集
* @throws SQLException
*/
public static boolean executeSQL(Statement statement) throws SQLException {
// 测试的SQL语句
String testSQL = "select 1 from dual";
// 执行SQL语句,如果执行返回结果为ResultSet对象则为true,其他为false。
boolean isSuccess = statement.execute(testSQL);
System.out.println("执行 \t" + testSQL + " 的结果为:" + isSuccess);
return isSuccess;
} /**
* 调用statement对象的executeQuery方法执行SQL语句,返回类型为ResultSet
*
* @param statement
* @return ResultSet对象,执行SQL语句返回的结果集
* @throws SQLException
*/
public static ResultSet executeQuerySQL(Statement statement) throws SQLException {
// SQL语句
String querySql = "select '#'|| name ,stu_num , stu_class, stu_major from student";
// DDL语句
String ddlSql = "alter table student add birth date";
// 结果集
ResultSet rs = statement.executeQuery(querySql);
System.out.println("执行\t" + querySql + " 的结果为:");
ResultUtil.printResultSet(rs);
return rs;
} /**
* 调用statement对象的executeUpdate方法。示例:更新表
*
* @param statement
* @return
* @throws SQLException
*/
public static int executeUpdateSQL(Statement statement) throws SQLException {
// 更新语句
String sql = "update student set birth = null";
// 更新记录数量
int updateRowNum = statement.executeUpdate(sql);
System.out.println("执行\t" + sql + ",更新行数为:" + updateRowNum);
return updateRowNum;
} /**
* 调用statement对象的executeBatch方法。示例为:批量插入表
*
* @param statement
* @return
* @throws SQLException
*/
public static int[] executeBatchSQL(Statement statement) throws SQLException {
for (int i = 101; i < 200; i++) {
String batchSql = "insert into student values (" + "'rain" + i + "'," + i + ","
+ "'287班" + "'," + "'math" + "'," + "null)";
statement.addBatch(batchSql);
}
int[] count = statement.executeBatch();
System.out.println(Arrays.toString(count));
return count;
}

PreparedStatement

PreparedStatement对象继承自Statement对象。相比于Statement,它有两个特点。

  1. 特点1:SQL语句经过预编译,所以效率执行较高。需要确保SQL结构不变。
  2. 特点2:在执行的SQL语句中通过占位符?表示IN参数。所以PrepareStatement在执行SQL语句时,需要根据占位符的索引值或者是数据库表中列的数据类型来设置参数。在使用此对象时需要知道数据库表中列与参数的对应关系,数据库数据类型与Java数据类型的映射关系。IN参数表示Java程序传递到数据库的参数。OUT参数指数据库返回给Java程序的参数,例如调用存储过程会处理此类型的参数。

创建对象

参考Connection对象

设置参数

基本数据类型

setXX(paramIndex,value):XX有三种类型

基础数据类型:表示byte,short,boolean,int,long,float,double,String。

基本数据对象:BigDecimal,

数组:bytes,

时间

setXX(paramIndex,value):XX表示时间类型,可以是Date,Time,TimeStamp,都包含在java.sql包中。

setXX(paramIndex,value,calendar)

JAVA对象

setURL(paramIndex,value):

setNull(paramIndex,sqlType)

setNull(paramIndex,sqlType,typeName)

setObject(paramIndex,obj,sqlType,scaleOrLength):参数paramIndex表示索引值,obj表示要插入的对象,如果为InputStream,scaleOrLength表示流的大小,如果为Reader,scaleOrLength表示字符流的长度。sqlType表示实现了SQLData接口的任意对象,该接口有writeSQL方法,将对象的内容写入到流当中

setObject(paramIndex,obj):参数含义同上。重载方法。

二进制流

setXX(paramIndex,inputStream):XX表示流的类型,可以是ASCIIStream,BinaryStream,CharacterStream。

当为ASCIIStream时,表示字符转换为流使用的字符集为ASCII码。

当为CharacterStream时,第二个参数类型为Reader。

setXX(paramIndex,inputStream,intLength)

setXX(paramIndex,InputStream,longLength)

大对象

setXX(paramIndex,value):XX表示大对象类型,可以是BLOB,CLOB,NCLOB。

当为CLOB,NCLOB时,第二个参数类型为Reader。

setXX(paramIndex,inputStream)

setXX(paramIndex,inputStream,length)

数据类型映射

Java2SQL

Java数据类型映射为数据库数据类型在插入数据的过程中。例如PreparedStatement.setXX(paramIndex,value)。

字符串

  1. Char:固定长度的字符串,最多存储2000字节的信息。默认长度为1。长度不足时,使用空格填充。映射为String类型
  2. NCHAR:包含UNICODE格式数据的定长字符串。映射为Java类型为String类型
  3. VARCHAR:长度可变的字符串。映射Java类型为String类型
  4. VARCHAR2:长度可变的字符串,最多存储4000字节的信息。长度不足时不会填充空格。映射类型为String类型
  5. NVARCHAR2:包含UNICODE格式数据的长度可变的字符串。映射类型为String类型
  6. LONG VARCHAR:用来存储multi-megabyte(可以理解为很大的意思) 字符串。映射类型为流类型,例如CharacterStream

数字

整数

  1. bit:存储1位二进制数字,表示0或者1。Oracle不支持。映射类型为布尔,当然char(1)也可以表示
  2. tinyint:存储1个字节的整数。存储范围为0-255或-128-127。Oracle不支持。映射类型为byte
  3. smallint:存储2个字节的整数。存储范围为-32768-32767。映射类型为short
  4. integer:存储4个字节的整数,存储范围为 -2147483648-2147483647。映射类型为int,或long类型。
  5. bigInteger:存储8个字节的整数,存储范围为-9223372026854775808-9223372026854775807。Oracle不支持
  6. 有小数时会被四舍五入。映射类型为BigDecimal对象,

浮点数

  1. real:The REAL datatype is a floating-point number with a binary precision of 63, or 18 decimal.。底层实现机制为Number,占用22个字节。映射类型为float
  2. double(n):参数n表示数字的精度。使用十进制来表示数字。映射类型为double
  3. float(n):参数n表示数字的精度。取值范围为1-126。映射类型为double。
  4. binary_float:存储4个字节浮点数,可以支持至少6位精度。需要5个字节的存储空间。使用二进制来表示数字。映射类型为float。
  5. bianry_double:存储8个字节浮点数,可以支持至少15位精度。需要9个字节的存储空间。使用二进制来表示数字。映射类型为double。

大数字

  1. number(total,scale):参数total表示数字的总位数,scale表示小数位的个数。例如11.2,total的值为3,scale的值为1。映射类型为bigDecimal对象或long类型。
  2. decimal:与number含义相同,底层就是number类型。

时间

  1. Date:表示日期,由年,月,日组成。映射为java.sql.Date对象。时分秒由0补充
  2. time:表示时间,由时,分,秒组成。映射为java.sql.Time对象。Oracle数据库不支持。
  3. timeStamp:表示时刻,由年,月,日,时,分,秒,毫秒,纳秒组成。映射为java.sql.TimeStamp对象。

时间可以包含时区。

大数据量

  1. BLOB:存储二进制流的大数据文件。映射java数据类型为inputStream,或者是java.sql.BLOB对象
  2. CLOB:存储文本的大数据。映射java数据类型为Reader,或者是java.sql.CLOB对象。
  3. NCLOB:存储文本的大数据,编码格式为Unicode 映射java数据类型为NCLOB,或者是java.sql.NCLOB对象。存储量过大时,性能比较低,所以一般大文本数据不存在数据库当中。

SQL2Java

Types类中用常量表示SQL类型。复杂的SQL类型有特殊的Java对象与之对应

字符串

CHAR,NCHAR,VARCHAR,NVARCHAR,LONGVARCHAR

数字

BIT,TINYINT,SMALLINT,INTEGER ,REAL,DOUBLE,FLOAT,DECIMAL ,NUMERIC,BIGINT

时间

DATE,TIME,TIME_WITH_ZONE,TIMESTAMP,TIMESTAMP_WITH_TIMEZONE。

对象

如果不特别指明,都在Java.sql包下面

DATE,TIME,TIMESTAMP。

对象

Array,DATALINK,DISTINCT,JAVA_OBJECT,REF,REF_CURSOR,SQLXML,STRUCT。

对象

ARRAY,Struct,SQLXML,REF。

大数据量

BLOB,NCLOB,CLOB。

对象

BLOB,CLOB,NCLOB。

流数据

BINARY,VARBINARY,

其他

NULL,OTHER,ROWID。

对象

ROWID

示例如下

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import com.rain.bean.Address;
import com.rain.util.DataSourceUtil;
import com.rain.util.DateUtil; /**
* 演示PreparedStatement对象的方法。 本示例中使用的数据库表为dataTypeMapping表, 字段除主键id外,名称都为XX_DATA,其中XX表示Oracle的数据库类型。
* 本示例中使用的文件jdbcLog.txt是任意选取的一个日志文件,大小为2M
*
*/
public class PreparedStatementSample {
private final static String sql =
"insert into dataTypeMapping values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
// Char数据类型的默认值
private final static String CHAR_DEFAULT_VALUE = "Hello World";
// Varchar数据类型的默认值
private final static String VARCHAR_DEFAULT_VALUE = "我们都是祖国的好青年";
// varchar2数据类型的默认值
private final static String VARCHAR2_DEFAULT_VALUE = "我们都是祖国的好青年";
// nchar数据类型的默认值
private final static String NCHAR_DEFAULT_VALUE = "Hello World";
// nvarchar2数据类型的默认值
private final static String NVARCHAR2_DEFAULT_VALUE = "我们都是祖国的好青年"; public static void main(String[] args) throws Exception {
// 创建preparedStatement
PreparedStatement preStatement = createPreStatement(sql);
// 设置主键
preStatement.setInt(1, 3);
// 设置字符串类型的参数
preStatement = setCharTypeData(preStatement);
// 设置数字类型的参数
preStatement = setNumberTypeData(preStatement);
// 设置时间类型的参数
preStatement = setDateTypeData(preStatement);
// 设置大数据类型的参数
preStatement = setBigTypeData(preStatement);
// 设置对象类型的参数
preStatement = setObjTypeData(preStatement);
// 执行SQL语句
int count = preStatement.executeUpdate();
//
System.out.println("执行\t" + sql + "语句,插入的数据条数为:" + count);
} /**
* 创建PreparedStatement对象
*
* @return Statement对象
* @throws SQLException
*/
public static PreparedStatement createPreStatement(String sql) throws SQLException {
// 创建Connection对象
Connection conn = DataSourceUtil.getConnectionByDriver();
// 创建Statement对象
PreparedStatement preStatement = conn.prepareStatement(sql);
return preStatement;
} /**
* 插入字符串类型的参数
*
* @param preStatement
* @return
* @throws SQLException
* @throws FileNotFoundException
*/
public static PreparedStatement setCharTypeData(PreparedStatement preStatement)
throws SQLException, FileNotFoundException {
// char类型的数据格式
preStatement.setString(2, CHAR_DEFAULT_VALUE);
// varchar类型的数据格式
preStatement.setString(3, VARCHAR_DEFAULT_VALUE);
// NChar类型的数据格式
preStatement.setNString(4, NCHAR_DEFAULT_VALUE);
// varchar2类型的数据格式
preStatement.setString(5, VARCHAR2_DEFAULT_VALUE);
// NVarchar2类型的数据格式
preStatement.setNString(6, NVARCHAR2_DEFAULT_VALUE);
// LONGVARCHAR类型的数据格式
Reader reader = new FileReader("jdbcLog.txt");
preStatement.setCharacterStream(7, reader);
return preStatement;
} /**
* 插入数字类型的参数
*
* @param preStatement
* @return
* @throws SQLException
*/
public static PreparedStatement setNumberTypeData(PreparedStatement preStatement)
throws SQLException {
// INT 数据类型,因为ORACLE不支持BIT和TINYINT类型
preStatement.setShort(8, (short) 25);
// SMALLINT 数据类型
preStatement.setShort(9, (short) 327);
// INTEGER 数据类型
preStatement.setInt(10, 21474);
// BIGINteger数据类型, Oracle 不支持
preStatement.setLong(11, 214748L);
// REAL 浮点数类型
preStatement.setFloat(12, 12.12f);
// DOUBLE 浮点数类型
preStatement.setDouble(13, 123.456);
// NUMBER 数据类型
BigDecimal decimal = new BigDecimal(19989898);
preStatement.setBigDecimal(14, decimal);
return preStatement;
} /**
* 插入时间类型的参数
*
* @param preStatement
* @return
* @throws SQLException
*/
public static PreparedStatement setDateTypeData(PreparedStatement preStatement)
throws SQLException {
// 设置Date日期类型的参数
Calendar calendar = Calendar.getInstance();
Date date = new Date(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
preStatement.setDate(15, date);
// 设置Time时间类型的参数
Time time = new Time(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND));
preStatement.setTime(16, time);
// 设置TimeStamp类型的参数
Timestamp timeStamp = new Timestamp(calendar.toInstant().toEpochMilli());
preStatement.setTimestamp(17, timeStamp);
return preStatement;
} /**
* 插入大数据类型的对象,BLOB,CLOB,NCLOB
*
* @param preStatement
* @return
* @throws FileNotFoundException
* @throws SQLException
*/
public static PreparedStatement setBigTypeData(PreparedStatement preStatement)
throws FileNotFoundException, SQLException {
long before = System.currentTimeMillis();
// 设置BLOB对象
InputStream input = new FileInputStream("jdbcLog.txt");
preStatement.setBlob(18, input);
// 设置CLOB对象
Reader reader = new FileReader("pom.xml");
preStatement.setClob(19, reader);
// 设置NCLOB对象
Reader wordDoc = new FileReader("摘要.docx");
preStatement.setNClob(20, wordDoc);
long after = System.currentTimeMillis();
System.out.println("共用了 " + DateUtil.getInterval(after - before) + "时间");
return preStatement;
} /**
* 插入对象类型的数据
*
* @param preStatement
* @return
* @throws SQLException
*/
public static PreparedStatement setObjTypeData(PreparedStatement preStatement)
throws SQLException {
// 设置NULL类型的对象,
preStatement.setNull(21, Types.NVARCHAR);
// 设置Address类型的对象
Address address = new Address();
// 设置国家
address.setCountry("中国");
// 设置地区
address.setProvince("江苏");
// 设置城市
address.setCity("杭州");
preStatement.setObject(22, address.toString(), Types.VARCHAR);
return preStatement;
}
}

CallableStatement

TODO

参考资料

博客: Oracle数据库数据类型  http://www.cnblogs.com/kerrycode/archive/2013/08/17/3265120.html

05-11 20:44