首页 > 代码库 > API解读第二篇——执行SQL的核心对象(JDBC)
API解读第二篇——执行SQL的核心对象(JDBC)
结构图
核心对象
Statement
Statement主要用来执行SQL语句。它执行SQL语句的步骤为:
- 第一步:创建statement对象。
- 第二步:配置statement对象,此步骤可以忽略。
- 第三步:调用statement的executeXXX方法执行SQL语句。
- 第四步:处理结果集。示例中只是打印结果集。
- 第五步:关闭statement对象。
Statement执行SQL语句的方法有四种类型。
- execute执行返回结果包含一个或者多个结果集,或结果包含一个或多个更新记录数量的SQL语句。返回类型为布尔,当执行SQL语句返回结果为ResultSet对象时为true,其他情形为false。
- executeQuery执行返回结果为ResultSet对象的SQL语句,例如select语句。返回类型为ResultSet对象。
- executeUpdate执行返回结果为更新记录数量的SQL语句,例如update,Insert,delete语句。它也可以用来DDL语句。返回值类型为int。当执行update,insert,delete语句时,int值表示更新记录数量,其他情形返回0。
- executeLargeUpdate方法与executeUpdate方法类似。适用于更新数量较多的情况。返回值类型为Long
创建对象
参考Connection对象
get&set
1 /**----------Statement对象相关-----------**/ 2 // 设置支持Pooled 3 statement.setPoolable(true); 4 System.out.println("statement语句的是否支持Pooled:" + statement.isPoolable()); 5 System.out.println("statement语句是否已经关闭:" + statement.isClosed()); 6 /**----------SQL执行过程----------**/ 7 // 建议结果集的排序方式,类型有三种,FETCH_FORWARD,FETCH_REVERSE,FETCH_UNKONWN 8 statement.setFetchDirection(ResultSet.FETCH_REVERSE); 9 // 建议每一次接收结果集的条数 10 statement.setFetchSize(10); 11 // 设置ResultSet最大的条数 12 statement.setMaxRows(10); 13 // 设置字段内容最大的字节数 14 statement.setMaxFieldSize(100); 15 // 设置执行sql语句的超时时间 16 statement.setQueryTimeout(1); 17 // 设置是否执行Escape类型的SQL语法。 18 statement.setEscapeProcessing(false); 19 /**-----------结果集相关信息------------**/ 20 System.out.println("statement语句的FetchDirection为:" + statement.getFetchDirection()); 21 System.out.println("statement语句的FetchSize为:" + statement.getFetchSize()); 22 System.out.println("statement语句的maxFieldSize:" + statement.getMaxFieldSize()); 23 System.out.println("statement语句的maxRows为:" + statement.getMaxRows()); 24 System.out.println("statement语句的queryTimeOut为:" + statement.getQueryTimeout()); 25 System.out.println("statement语句的结果集更新方式:" + statement.getResultSetConcurrency()); 26 System.out.println("statement语句的结果集关闭方式:" + statement.getResultSetHoldability()); 27 System.out.println("statement语句的结果集的遍历方式:" + statement.getResultSetType()); 28 System.out.println("statement语句的LargeMaxRows为:" + statement.getLargeMaxRows());
executeSQL
- execute(sql):参数sql表示一条sql语句。例如select 1 from dual;select 2 from dual;它包含两条sql语句。这种情形是不允许的
- execute(sql,autoGeneratedKeys):参数autoGneratedKeys,TODO
- execute(sql,columnIndexs):参数columnIndexs表示列的索引值,从1开始。类型为int数组
- execute(sql,columnNames):参数columnNames表示列名称,类型为String数组。
executeUpdate,executeQuery,executeLargeUpdate拥有和execute方法相同的参数和重载方法
批量
- addBatch(sql):在批量执行的SQL语句中添加sql语句。参数sql表示一条sql语句。sql语句的类型可以是delete,update,insert的任意一种。执行每条SQL返回值类型为int。如果批量执行其他类型的SQL语句,可以使用存储过程。
- executeBatch:批量执行SQL,返回值为int数组。数组的每个值表示每条SQL语句更新记录数量的值
- executeLargeBatch:含义与executeBatch相同。返回值类型为Long数组。
- clearBatch:清空批量执行的SQL。
- cancel:取消正在执行的SQL语句。
示例如下:
1 /** 2 * 演示Statement对象的方法。 本示例中使用到的数据库表为student,该表字段为名称,学号,班级,主修课, 3 * 本示例中创建Statement调用的方法参考Connection,DriverManager,Driver等对象。 4 * 5 */ 6 public class StatementSample { 7 public static void main(String[] args) throws SQLException { 8 // 创建Statement对象 9 Statement statement = createStatement(); 10 // 使用execute方法执行sql语句 11 executeSQL(statement); 12 // 使用executeQuery方法执行sql语句 13 executeQuerySQL(statement); 14 // 使用executeUpdate方法执行sql语句 15 executeUpdateSQL(statement); 16 } 17 18 /** 19 * 创建Statement对象 20 * 21 * @return Statement对象 22 * @throws SQLException 23 */ 24 public static Statement createStatement() throws SQLException { 25 // 创建Connection对象 26 Connection conn = DataSourceUtil.getConnectionByDriver(); 27 // 创建Statement对象 28 Statement statement = conn.createStatement(); 29 return statement; 30 } 31 32 /** 33 * 调用Statement对象的execute方法,示例为:select 1 from dual 测试语句 34 * 35 * @return ResultSet 结果集 36 * @throws SQLException 37 */ 38 public static boolean executeSQL(Statement statement) throws SQLException { 39 // 测试的SQL语句 40 String testSQL = "select 1 from dual"; 41 // 执行SQL语句,如果执行返回结果为ResultSet对象则为true,其他为false。 42 boolean isSuccess = statement.execute(testSQL); 43 System.out.println("执行 \t" + testSQL + " 的结果为:" + isSuccess); 44 return isSuccess; 45 } 46 47 /** 48 * 调用statement对象的executeQuery方法执行SQL语句,返回类型为ResultSet 49 * 50 * @param statement 51 * @return ResultSet对象,执行SQL语句返回的结果集 52 * @throws SQLException 53 */ 54 public static ResultSet executeQuerySQL(Statement statement) throws SQLException { 55 // SQL语句 56 String querySql = "select ‘#‘|| name ,stu_num , stu_class, stu_major from student"; 57 // DDL语句 58 String ddlSql = "alter table student add birth date"; 59 // 结果集 60 ResultSet rs = statement.executeQuery(querySql); 61 System.out.println("执行\t" + querySql + " 的结果为:"); 62 ResultUtil.printResultSet(rs); 63 return rs; 64 } 65 66 67 /** 68 * 调用statement对象的executeUpdate方法。示例:更新表 69 * 70 * @param statement 71 * @return 72 * @throws SQLException 73 */ 74 public static int executeUpdateSQL(Statement statement) throws SQLException { 75 // 更新语句 76 String sql = "update student set birth = null"; 77 // 更新记录数量 78 int updateRowNum = statement.executeUpdate(sql); 79 System.out.println("执行\t" + sql + ",更新行数为:" + updateRowNum); 80 return updateRowNum; 81 } 82 83 /** 84 * 调用statement对象的executeBatch方法。示例为:批量插入表 85 * 86 * @param statement 87 * @return 88 * @throws SQLException 89 */ 90 public static int[] executeBatchSQL(Statement statement) throws SQLException { 91 for (int i = 101; i < 200; i++) { 92 String batchSql = "insert into student values (" + "‘rain" + i + "‘," + i + "," 93 + "‘287班" + "‘," + "‘math" + "‘," + "null)"; 94 statement.addBatch(batchSql); 95 } 96 int[] count = statement.executeBatch(); 97 System.out.println(Arrays.toString(count)); 98 return count; 99 }
PreparedStatement
PreparedStatement对象继承自Statement对象。相比于Statement,它有两个特点。
- 特点1:SQL语句经过预编译,所以效率执行较高。需要确保SQL结构不变。
- 特点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)。
字符串
- Char:固定长度的字符串,最多存储2000字节的信息。默认长度为1。长度不足时,使用空格填充。映射为String类型
- NCHAR:包含UNICODE格式数据的定长字符串。映射为Java类型为String类型
- VARCHAR:长度可变的字符串。映射Java类型为String类型
- VARCHAR2:长度可变的字符串,最多存储4000字节的信息。长度不足时不会填充空格。映射类型为String类型
- NVARCHAR2:包含UNICODE格式数据的长度可变的字符串。映射类型为String类型
- LONG VARCHAR:用来存储multi-megabyte(可以理解为很大的意思) 字符串。映射类型为流类型,例如CharacterStream
数字
整数
- bit:存储1位二进制数字,表示0或者1。Oracle不支持。映射类型为布尔,当然char(1)也可以表示
- tinyint:存储1个字节的整数。存储范围为0-255或-128-127。Oracle不支持。映射类型为byte
- smallint:存储2个字节的整数。存储范围为-32768-32767。映射类型为short
- integer:存储4个字节的整数,存储范围为 -2147483648-2147483647。映射类型为int,或long类型。
- bigInteger:存储8个字节的整数,存储范围为-9223372026854775808-9223372026854775807。Oracle不支持
- 有小数时会被四舍五入。映射类型为BigDecimal对象,
浮点数
- real:The REAL datatype is a floating-point number with a binary precision of 63, or 18 decimal.。底层实现机制为Number,占用22个字节。映射类型为float
- double(n):参数n表示数字的精度。使用十进制来表示数字。映射类型为double
- float(n):参数n表示数字的精度。取值范围为1-126。映射类型为double。
- binary_float:存储4个字节浮点数,可以支持至少6位精度。需要5个字节的存储空间。使用二进制来表示数字。映射类型为float。
- bianry_double:存储8个字节浮点数,可以支持至少15位精度。需要9个字节的存储空间。使用二进制来表示数字。映射类型为double。
大数字
- number(total,scale):参数total表示数字的总位数,scale表示小数位的个数。例如11.2,total的值为3,scale的值为1。映射类型为bigDecimal对象或long类型。
- decimal:与number含义相同,底层就是number类型。
时间
- Date:表示日期,由年,月,日组成。映射为java.sql.Date对象。时分秒由0补充
- time:表示时间,由时,分,秒组成。映射为java.sql.Time对象。Oracle数据库不支持。
- timeStamp:表示时刻,由年,月,日,时,分,秒,毫秒,纳秒组成。映射为java.sql.TimeStamp对象。
时间可以包含时区。
大数据量
- BLOB:存储二进制流的大数据文件。映射java数据类型为inputStream,或者是java.sql.BLOB对象
- CLOB:存储文本的大数据。映射java数据类型为Reader,或者是java.sql.CLOB对象。
- 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
示例如下
1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.FileReader; 4 import java.io.InputStream; 5 import java.io.Reader; 6 import java.math.BigDecimal; 7 import java.sql.Connection; 8 import java.sql.Date; 9 import java.sql.PreparedStatement; 10 import java.sql.SQLException; 11 import java.sql.Time; 12 import java.sql.Timestamp; 13 import java.sql.Types; 14 import java.util.Calendar; 15 import com.rain.bean.Address; 16 import com.rain.util.DataSourceUtil; 17 import com.rain.util.DateUtil; 18 19 /** 20 * 演示PreparedStatement对象的方法。 本示例中使用的数据库表为dataTypeMapping表, 字段除主键id外,名称都为XX_DATA,其中XX表示Oracle的数据库类型。 21 * 本示例中使用的文件jdbcLog.txt是任意选取的一个日志文件,大小为2M 22 * 23 */ 24 public class PreparedStatementSample { 25 private final static String sql = 26 "insert into dataTypeMapping values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 27 // Char数据类型的默认值 28 private final static String CHAR_DEFAULT_VALUE = "http://www.mamicode.com/Hello World"; 29 // Varchar数据类型的默认值 30 private final static String VARCHAR_DEFAULT_VALUE = "http://www.mamicode.com/我们都是祖国的好青年"; 31 // varchar2数据类型的默认值 32 private final static String VARCHAR2_DEFAULT_VALUE = "http://www.mamicode.com/我们都是祖国的好青年"; 33 // nchar数据类型的默认值 34 private final static String NCHAR_DEFAULT_VALUE = "http://www.mamicode.com/Hello World"; 35 // nvarchar2数据类型的默认值 36 private final static String NVARCHAR2_DEFAULT_VALUE = "http://www.mamicode.com/我们都是祖国的好青年"; 37 38 public static void main(String[] args) throws Exception { 39 // 创建preparedStatement 40 PreparedStatement preStatement = createPreStatement(sql); 41 // 设置主键 42 preStatement.setInt(1, 3); 43 // 设置字符串类型的参数 44 preStatement = setCharTypeData(preStatement); 45 // 设置数字类型的参数 46 preStatement = setNumberTypeData(preStatement); 47 // 设置时间类型的参数 48 preStatement = setDateTypeData(preStatement); 49 // 设置大数据类型的参数 50 preStatement = setBigTypeData(preStatement); 51 // 设置对象类型的参数 52 preStatement = setObjTypeData(preStatement); 53 // 执行SQL语句 54 int count = preStatement.executeUpdate(); 55 // 56 System.out.println("执行\t" + sql + "语句,插入的数据条数为:" + count); 57 } 58 59 /** 60 * 创建PreparedStatement对象 61 * 62 * @return Statement对象 63 * @throws SQLException 64 */ 65 public static PreparedStatement createPreStatement(String sql) throws SQLException { 66 // 创建Connection对象 67 Connection conn = DataSourceUtil.getConnectionByDriver(); 68 // 创建Statement对象 69 PreparedStatement preStatement = conn.prepareStatement(sql); 70 return preStatement; 71 } 72 73 /** 74 * 插入字符串类型的参数 75 * 76 * @param preStatement 77 * @return 78 * @throws SQLException 79 * @throws FileNotFoundException 80 */ 81 public static PreparedStatement setCharTypeData(PreparedStatement preStatement) 82 throws SQLException, FileNotFoundException { 83 // char类型的数据格式 84 preStatement.setString(2, CHAR_DEFAULT_VALUE); 85 // varchar类型的数据格式 86 preStatement.setString(3, VARCHAR_DEFAULT_VALUE); 87 // NChar类型的数据格式 88 preStatement.setNString(4, NCHAR_DEFAULT_VALUE); 89 // varchar2类型的数据格式 90 preStatement.setString(5, VARCHAR2_DEFAULT_VALUE); 91 // NVarchar2类型的数据格式 92 preStatement.setNString(6, NVARCHAR2_DEFAULT_VALUE); 93 // LONGVARCHAR类型的数据格式 94 Reader reader = new FileReader("jdbcLog.txt"); 95 preStatement.setCharacterStream(7, reader); 96 return preStatement; 97 } 98 99 /** 100 * 插入数字类型的参数 101 * 102 * @param preStatement 103 * @return 104 * @throws SQLException 105 */ 106 public static PreparedStatement setNumberTypeData(PreparedStatement preStatement) 107 throws SQLException { 108 // INT 数据类型,因为ORACLE不支持BIT和TINYINT类型 109 preStatement.setShort(8, (short) 25); 110 // SMALLINT 数据类型 111 preStatement.setShort(9, (short) 327); 112 // INTEGER 数据类型 113 preStatement.setInt(10, 21474); 114 // BIGINteger数据类型, Oracle 不支持 115 preStatement.setLong(11, 214748L); 116 // REAL 浮点数类型 117 preStatement.setFloat(12, 12.12f); 118 // DOUBLE 浮点数类型 119 preStatement.setDouble(13, 123.456); 120 // NUMBER 数据类型 121 BigDecimal decimal = new BigDecimal(19989898); 122 preStatement.setBigDecimal(14, decimal); 123 return preStatement; 124 } 125 126 /** 127 * 插入时间类型的参数 128 * 129 * @param preStatement 130 * @return 131 * @throws SQLException 132 */ 133 public static PreparedStatement setDateTypeData(PreparedStatement preStatement) 134 throws SQLException { 135 // 设置Date日期类型的参数 136 Calendar calendar = Calendar.getInstance(); 137 Date date = new Date(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 138 calendar.get(Calendar.DAY_OF_MONTH)); 139 preStatement.setDate(15, date); 140 // 设置Time时间类型的参数 141 Time time = new Time(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), 142 calendar.get(Calendar.SECOND)); 143 preStatement.setTime(16, time); 144 // 设置TimeStamp类型的参数 145 Timestamp timeStamp = new Timestamp(calendar.toInstant().toEpochMilli()); 146 preStatement.setTimestamp(17, timeStamp); 147 return preStatement; 148 } 149 150 /** 151 * 插入大数据类型的对象,BLOB,CLOB,NCLOB 152 * 153 * @param preStatement 154 * @return 155 * @throws FileNotFoundException 156 * @throws SQLException 157 */ 158 public static PreparedStatement setBigTypeData(PreparedStatement preStatement) 159 throws FileNotFoundException, SQLException { 160 long before = System.currentTimeMillis(); 161 // 设置BLOB对象 162 InputStream input = new FileInputStream("jdbcLog.txt"); 163 preStatement.setBlob(18, input); 164 // 设置CLOB对象 165 Reader reader = new FileReader("pom.xml"); 166 preStatement.setClob(19, reader); 167 // 设置NCLOB对象 168 Reader wordDoc = new FileReader("摘要.docx"); 169 preStatement.setNClob(20, wordDoc); 170 long after = System.currentTimeMillis(); 171 System.out.println("共用了 " + DateUtil.getInterval(after - before) + "时间"); 172 return preStatement; 173 } 174 175 /** 176 * 插入对象类型的数据 177 * 178 * @param preStatement 179 * @return 180 * @throws SQLException 181 */ 182 public static PreparedStatement setObjTypeData(PreparedStatement preStatement) 183 throws SQLException { 184 // 设置NULL类型的对象, 185 preStatement.setNull(21, Types.NVARCHAR); 186 // 设置Address类型的对象 187 Address address = new Address(); 188 // 设置国家 189 address.setCountry("中国"); 190 // 设置地区 191 address.setProvince("江苏"); 192 // 设置城市 193 address.setCity("杭州"); 194 preStatement.setObject(22, address.toString(), Types.VARCHAR); 195 return preStatement; 196 } 197 }
CallableStatement
TODO
参考资料
博客: Oracle数据库数据类型 http://www.cnblogs.com/kerrycode/archive/2013/08/17/3265120.html
API解读第二篇——执行SQL的核心对象(JDBC)