目录
一、Java和数据库交互主要分为三步:
二、事务
三、DriverManager
四、Connection
五、Statement
六、PreparedStatement
七、CallableStatement
八、ResultSet
九、DatabaseMetaData
十、ResultSetMetaData
十一、连接池
一、Java和数据库交互主要分为三步:
1、加载驱动,由各个数据库厂商自己实现,
2、获得数据库链接,通常是通过scoket获取数据库的链接,所以比较消耗资源。
3、发送sql语句到数据库。
下面以mysql为例:
1)加载驱动,首先要导入mysql的驱动jar mysql-connector-java-5.1.9.jar,其次加载
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
2) 获取数据库链接
Connection con = null;
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/datatest","root","root"); //url username password
3)发送sql到数据库
这里java提供了三中方式:
- Statement接口
Statement stat = null;
//3、向数据库发送sql语句
stat = con.createStatement();
String sql = "insert into user (name,age) values ('zhangsan',18) ";
stat.execute(sql);
Java.sql. PreparedStatement extends Statement
PreparedStatement preparedStat =null;
String sql = "insert into user (name,age,date) values (?,?,?) ";
preparedStat = con.prepareStatement(sql);
preparedStat.setString(1, "lisi");
preparedStat.setInt(2, 19);
preparedStat.setDate(3, new java.sql.Date(System.currentTimeMillis())); preparedStat.execute();
PreparedStatement是对发送到数据库的sql进行预编译的,而Statement每次把sql发送到数据库都需要编译一次,因此,对一只执行一次的sql,使用Statement相对效率更高,而对同一个sql需要进行多次操作,则使用PreparedStatement。
public interface CallableStatement extends PreparedStatemen
只要支持对存储过程的支持,
DriverManager,Statement,PreparedStatement,CallableStatement,Connection以及查询结果ResultSet进行详细讲解。
二、事务
一组sql要么同时成功,要么同时失败的sql语句,是数据库操作的一个执行单元。
事务开始于:
连接到数据库上,并执行一条DML语句(delete、update、insert)
前一个事务结束后,又输入另外一条DML语句。
事务结束于:
执行一条Commit或rollback语句;
执行一个DDL语句,例如create table 语句,这种情况下会自动执行commit语句;
执行一个DCL语句,例如,great语句,这种情况下会自动执行commit语句;
断开与数据库的链接;
执行了一条DML语句,该语句却失败了,在这种情况下,为会这个无效的DML语句执行ROLLBACK语句。
事务的四大基本特性(ACID特性)
原子性:事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
一致性:事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
持久性:意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
隔离性:多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
三、DriverManager
public class DriverManager extends Object 管理一组 JDBC 驱动程序的基本服务。
方法摘要 | |
static void | deregisterDriver(Driver |
static Connection | getConnection(String |
static Connection | getConnection(String url, Properties |
static Connection | getConnection(String url, String user, String |
static Driver | getDriver(String |
static Enumeration<Driver> | getDrivers()获取带有当前调用者可以访问的所有当前已加载 JDBC 驱动程序的 Enumeration。 |
static int | getLoginTimeout()获取驱动程序试图登录到某一数据库时可以等待的最长时间,以秒为单位。 |
static PrintStream | getLogStream()已过时。 |
static PrintWriter | getLogWriter() 获取日志 writer。 |
static void | println(String |
static void | registerDriver(Driver |
static void | setLoginTimeout(int seconds)设置驱动程序试图连接到某一数据库时将等待的最长时间,以秒为单位。 |
static void | setLogStream(PrintStream out)已过时。 |
static void | setLogWriter(PrintWriter |
四、Connection
public interface Connection extends Wrapper, AutoCloseable
与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
Connection
对象的数据库能够提供描述其表、所支持的 SQL 语法、存储过程、此连接功能等等的信息。此信息是使用 getMetaData
方法获得的。
注:在配置 Connection
时,JDBC 应用程序应该使用适当的 Connection
方法,比如 setAutoCommit
或 setTransactionIsolation
。在有可用的 JDBC 方法时,应用程序不能直接调用 SQL 命令更改连接的配置。默认情况下,Connection
对象处于自动提交模式下,这意味着它在执行每个语句后都会自动提交更改。如果禁用了自动提交模式,那么要提交更改就必须显式调用 commit
方法;否则无法保存数据库更改。
使用 JDBC 2.1 核心 API 创建的新 Connection
对象有一个与之关联的最初为空的类型映射。用户可以为此类型映射中的 UDT 输入一个自定义映射关系。在使用 ResultSet.getObject
方法从数据源中获取 UDT 时,getObject
方法将检查该连接的类型映射是否有对应该 UDT 的条目。如果有,那么 getObject
方法将该 UDT 映射到所指示的类。如果没有条目,则使用标准映射关系映射该 UDT。
用户可以创建一个新的类型映射,该映射是一个 java.util.Map
对象,可在其中创建一个条目,并将该条目传递给可以执行自定义映射关系的 java.sql
方法。在这种情况下,该方法将使用给定的类型映射,而不是与连接关联的映射。
例如,以下代码片段指定 SQL 类型 ATHLETES
将被映射到 Java 编程语言中的 Athletes
类。该代码片段为 Connection
对象 con
获取类型映射,并在其中插入条目,然后使用新的条目将该类型映射设置为连接的类型映射。
java.util.Map map = con.getTypeMap();
map.put("mySchemaName.ATHLETES", Class.forName("Athletes"));
con.setTypeMap(map);
字段摘要 | |
static int | TRANSACTION_NONE |
static int | TRANSACTION_READ_COMMITTED |
static int | TRANSACTION_READ_UNCOMMITTED |
static int | TRANSACTION_REPEATABLE_READ |
static int | TRANSACTION_SERIALIZABLE |
方法摘要 | |
void | clearWarnings()清除为此 Connection 对象报告的所有警告。 |
void | close()立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。 |
void | commit()使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。 |
Array | createArrayOf(String typeName, Object[] elements)创建 Array 对象的工厂方法。 |
Blob | createBlob() 构造实现 Blob 接口的对象。 |
Clob | createClob()构造实现 Clob 接口的对象。 |
NClob | createNClob()构造实现 NClob 接口的对象。 |
SQLXML | createSQLXML()构造实现 SQLXML 接口的对象。 |
Statement | createStatement()创建一个 Statement 对象来将 SQL 语句发送到数据库。 |
Statement | createStatement(int resultSetType, int resultSetConcurrency)创建一个 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。 |
Statement | createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)创建一个 Statement 对象,该对象将生成具有给定类型、并发性和可保存性的 ResultSet 对象。 |
Struct | createStruct(String typeName, Object[] attributes)创建 Struct 对象的工厂方法。 |
boolean | getAutoCommit()获取此 Connection 对象的当前自动提交模式。 |
String | getCatalog()获取此 Connection 对象的当前目录名称。 |
Properties | getClientInfo()返回一个列表,它包含驱动程序支持的每个客户端信息属性的名称和当前值。 |
String | getClientInfo(String |
int | getHoldability()获取使用此 Connection 对象创建的 ResultSet 对象的当前可保存性。 |
DatabaseMetaData | getMetaData()获取一个 DatabaseMetaData 对象,该对象包含关于此 Connection 对象所连接的数据库的元数据。 |
int | getTransactionIsolation()获取此 Connection 对象的当前事务隔离级别。 |
Map<String,Class<?>> | getTypeMap()获取与此 Connection 对象关联的 Map 对象。 |
SQLWarning | getWarnings()获取此 Connection 对象上的调用报告的第一个警告。 |
boolean | isClosed()查询此 Connection 对象是否已经被关闭。 |
boolean | isReadOnly()查询此 Connection 对象是否处于只读模式。 |
boolean | isValid(int timeout)如果连接尚未关闭并且仍然有效,则返回 true。 |
String | nativeSQL(String |
CallableStatement | prepareCall(String |
CallableStatement | prepareCall(String |
CallableStatement | prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) |
PreparedStatement | prepareStatement(String |
PreparedStatement | prepareStatement(String |
PreparedStatement | prepareStatement(String |
PreparedStatement | prepareStatement(String sql, int resultSetType, int resultSetConcurrency) |
PreparedStatement | prepareStatement(String |
PreparedStatement | prepareStatement(String sql, String[] columnNames)创建一个能返回由给定数组指定的自动生成键的默认 PreparedStatement 对象。 |
void | releaseSavepoint(Savepoint |
void | rollback()取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。 |
void | rollback(Savepoint |
void | setAutoCommit(boolean autoCommit)将此连接的自动提交模式设置为给定状态。 |
void | setCatalog(String |
void | setClientInfo(Properties |
void | setClientInfo(String name, String value) |
void | setHoldability(int holdability)将使用此 Connection 对象创建的 ResultSet 对象的默认可保存性 (holdability) 更改为给定可保存性。 |
void | setReadOnly(boolean readOnly)将此连接设置为只读模式,作为驱动程序启用数据库优化的提示。 |
Savepoint | setSavepoint()在当前事务中创建一个未命名的保存点 (savepoint),并返回表示它的新 Savepoint 对象。 |
Savepoint | setSavepoint(String |
void | setTransactionIsolation(int level)试图将此 Connection 对象的事务隔离级别更改为给定的级别。 |
void | setTypeMap(Map<String,Class<?>> map)将给定的 TypeMap 对象安装为此 Connection 对象的类型映射。 |
setAutoCommit(Boolean b)方法默认置为true;就是每执行一条sql语句,就自动提交一次;对于批量操作sql语句,需要手动先设置connection对象的setAutoCommit(false); 执行完sql操作后在执行提交事务的操作方法commit()。
eg: 批量插入数据到数据库
public static void test1(){
Connection con = null;
Statement stat = null;
try {
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
try {
//2、获得驱动
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/datatest","root","root");
con.setAutoCommit(false);
//3、向数据库发送sql语句
stat = con.createStatement();
long start = System.currentTimeMillis();
for(int i = 0; i<1000;i++){
String sql = "insert into user (name,age) values ('zhangsan"+i+"',18)" ;
stat.addBatch(sql);
}
stat.executeBatch();
con.commit();
long end = System.currentTimeMillis();
System.out.println("插入1000条数据耗时"+(end-start)+"毫秒");
} catch (SQLException e) {
try {
con.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace(); }finally{
if(null != con)
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(null != stat)
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
五、Statement
public interface Statement extends Wrapper 用于执行静态 SQL 语句并返回它所生成结果的对象
字段摘要 | |
static int | CLOSE_ALL_RESULTS |
static int | CLOSE_CURRENT_RESULT |
static int | EXECUTE_FAILED |
static int | KEEP_CURRENT_RESULT |
static int | NO_GENERATED_KEYS |
static int | RETURN_GENERATED_KEYS |
static int | SUCCESS_NO_INFO |
方法摘要 | |
void | addBatch(String sql) |
void | cancel() |
void | clearBatch() |
void | clearWarnings() |
void | close() |
boolean | execute(String sql) |
boolean | execute(String sql, int autoGeneratedKeys) |
boolean | execute(String sql, int[] columnIndexes) |
boolean | execute(String sql, String[] columnNames) |
int[] | executeBatch() |
ResultSet | executeQuery(String sql) |
int | executeUpdate(String sql) |
int | executeUpdate(String sql, int autoGeneratedKeys) |
int | executeUpdate(String sql, int[] columnIndexes) |
int | executeUpdate(String sql, String[] columnNames) |
Connection | getConnection() |
int | getFetchDirection() |
int | getFetchSize() |
ResultSet | getGeneratedKeys() |
int | getMaxFieldSize() |
int | getMaxRows() |
boolean | getMoreResults() |
boolean | getMoreResults(int current) |
int | getQueryTimeout() |
ResultSet | getResultSet() |
int | getResultSetConcurrency() |
int | getResultSetHoldability() |
int | getResultSetType() |
int | getUpdateCount() |
SQLWarning | getWarnings() |
boolean | isClosed() |
boolean | isPoolable() |
void | setCursorName(String name) |
void | setEscapeProcessing(boolean enable) |
void | setFetchDirection(int direction) |
void | setFetchSize(int rows) |
void | setMaxFieldSize(int max) |
void | setMaxRows(int max) |
void | setPoolable(boolean poolable) |
void | setQueryTimeout(int seconds) |
六、PreparedStatement
public interface PreparedStatement extends Statement
表示预编译的 SQL 语句的对象。
SQL 语句被预编译并存储在 PreparedStatement
对象中。然后可以使用此对象多次高效地执行该语句。
注:用于设置 IN 参数值的设置方法(setShort
、setString
等等)必须指定与输入参数的已定义 SQL 类型兼容的类型。例如,如果 IN 参数具有 SQL 类型 INTEGER
,那么应该使用 setInt
方法。
如果需要任意参数类型转换,使用 setObject
方法时应该将目标 SQL 类型作为其参数。
在以下设置参数的示例中,con
表示一个活动连接:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
这样可防止statement中的sql注入等不安全问题。
方法摘要 | |
void | addBatch() |
void | clearParameters() |
boolean | execute() |
ResultSet | executeQuery() |
int | executeUpdate() |
ResultSetMetaData | getMetaData() |
ParameterMetaData | getParameterMetaData() |
void | setArray(int parameterIndex, Array x) |
void | setAsciiStream(int parameterIndex, InputStream x) |
void | setAsciiStream(int parameterIndex, InputStream x, int length) |
void | setAsciiStream(int parameterIndex, InputStream x, long length) |
void | setBigDecimal(int parameterIndex, BigDecimal x) |
void | setBinaryStream(int parameterIndex, InputStream x) |
void | setBinaryStream(int parameterIndex, InputStream x, int length) |
void | setBinaryStream(int parameterIndex, InputStream x, long length) |
void | setBlob(int parameterIndex, Blob x) |
void | setBlob(int parameterIndex, InputStream inputStream) |
void | setBlob(int parameterIndex, InputStream inputStream, long length) |
void | setBoolean(int parameterIndex, boolean x) |
void | setByte(int parameterIndex, byte x) |
void | setBytes(int parameterIndex, byte[] x) |
void | setCharacterStream(int parameterIndex, Reader reader) |
void | setCharacterStream(int parameterIndex, Reader reader, int length) |
void | setCharacterStream(int parameterIndex, Reader reader, long length) |
void | setClob(int parameterIndex, Clob x) |
void | setClob(int parameterIndex, Reader reader) |
void | setClob(int parameterIndex, Reader reader, long length) |
void | setDate(int parameterIndex, Date x) |
void | setDate(int parameterIndex, Date x, Calendar cal) |
void | setDouble(int parameterIndex, double x) |
void | setFloat(int parameterIndex, float x) |
void | setInt(int parameterIndex, int x) |
void | setLong(int parameterIndex, long x) |
void | setNCharacterStream(int parameterIndex, Reader value) |
void | setNCharacterStream(int parameterIndex, Reader value, long length) |
void | setNClob(int parameterIndex, NClob value) |
void | setNClob(int parameterIndex, Reader reader) |
void | setNClob(int parameterIndex, Reader reader, long length) |
void | setNString(int parameterIndex, String value) |
void | setNull(int parameterIndex, int sqlType) |
void | setNull(int parameterIndex, int sqlType, String typeName) |
void | setObject(int parameterIndex, Object x) |
void | setObject(int parameterIndex, Object x, int targetSqlType) |
void | setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) |
void | setRef(int parameterIndex, Ref x) |
void | setRowId(int parameterIndex, RowId x) |
void | setShort(int parameterIndex, short x) |
void | setSQLXML(int parameterIndex, SQLXML xmlObject) |
void | setString(int parameterIndex, String x) |
void | setTime(int parameterIndex, Time x) |
void | setTime(int parameterIndex, Time x, Calendar cal) |
void | setTimestamp(int parameterIndex, Timestamp x) |
void | setTimestamp(int parameterIndex, Timestamp x, Calendar cal) |
void | setUnicodeStream(int parameterIndex, InputStream x, int length) |
void | setURL(int parameterIndex, URL x) |
七、CallableStatement
public interface CallableStatement extends PreparedStatement
用于执行 SQL 存储过程的接口。JDBC API 提供了一个存储过程 SQL 转义语法,该语法允许对所有 RDBMS 使用标准方式调用存储过程。此转义语法有一个包含结果参数的形式和一个不包含结果参数的形式。如果使用结果参数,则必须将其注册为 OUT 参数。其他参数可用于输入、输出或同时用于二者。参数是根据编号按顺序引用的,第一个参数的编号是 1。
{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
{call <procedure-name>[(<arg1>,<arg2>, ...)]}
IN 参数值是使用继承自 PreparedStatement
的 set
方法设置的。在执行存储过程之前,必须注册所有 OUT 参数的类型;它们的值是在执行后通过此类提供的 get
方法获取的。
CallableStatement
可以返回一个 ResultSet
对象或多个 ResultSet
对象。多个 ResultSet
对象是使用继承自 Statement
的操作处理的。
为了获得最大的可移植性,某一调用的 ResultSet
对象和更新计数应该在获得输出参数的值之前处理。
下面讲解下存储过程的基本用法:
优点:
- 存储过程增强了SQL语言的功能和灵活性。存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
- 当SQL语句有变动时,可以只修改数据库中的存储过程而不必修改代码。
- 存储过程能实现较快的执行速度。如果某一操作包含大量的SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。
- 减少网络传输。在客户端调用一个存储过程当然比执行一串SQL传输的数据量要小。
- 存储过程可被作为一种安全机制来充分利用。系统管理员通过执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
缺点:
不同的数据库存储过程语法差异很大,不便于移植。
- 创建存储过程
create procedure sp_name()
begin
.........
end
- 调用存储过程
1.基本语法:call sp_name()
注意:存储过程名称后面必须加括号,哪怕该存储过程没有参数传递
- 删除存储过程
1.基本语法:
drop procedure sp_name//
2.注意事项
(1)不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程
- 其他常用命令
1.show procedure status
显示数据库中所有存储的存储过程基本信息,包括所属数据库,存储过程名称,创建时间等
2.show create procedure sp_name
显示某一个MySQL存储过程的详细信息
- mysql存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT
Create procedure|function([[IN |OUT |INOUT ] 参数名 数据类形...])
- IN 输入参数
表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
- OUT 输出参数
该值可在存储过程内部被改变,并可返回
- INOUT 输入输出参数
调用时指定,并且可被改变和返回
下面举例说明如何通过callableStatement调用存储过程。
1)、数据库首选需要创建存储过程
DROP PROCEDURE IF EXISTS datatest.`proc_case`;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_case`(IN type int)
BEGIN
#Routine body goes here...
DECLARE c varchar(500);
CASE type
WHEN 0 THEN
set c = 'param is 0';
WHEN 1 THEN
set c = 'param is 1';
ELSE
set c = 'param is others, not 0 or 1';
END CASE;
select c;
END
2)、java代码中调用该存储过程
package dataBaseConnection;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author:zhangfd
* @version:1.0
* @date:2017年7月2日 下午2:28:59
* @description:
*/
public class CallableStatementTest {
public static void main(String[] args) {
Connection con = null;
CallableStatement callst = null;
ResultSet rs = null;
con = ConnectionUtil.getMySqlcon();
String sql = "call datatest.proc_case(?)";
try {
callst = con.prepareCall(sql);
callst.setInt(1, 1);
rs = callst.executeQuery(); // 注意:所有调用存储过程的sql语句都是使用executeQuery方法执行!!!
while (rs.next()) {
String c = rs.getString("c");
System.out.println(c);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionUtil.close(con, callst, rs);
}
}
}
八、ResultSet
public interface ResultSet extends Wrapper
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。
默认的 ResultSet 对象不可更新,仅有一个向前移动的光标。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更新的 ResultSet 对象。以下代码片段(其中 con 为有效的 Connection 对象)演示了如何生成可滚动且不受其他更新影响的可更新结果集。有关其他选项,请参见 ResultSet 字段。
Statement stmt = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
ResultSet 接口提供用于从当前行获取列值的获取 方法(getBoolean、getLong 等)。可以使用列的索引编号或列的名称获取值。一般情况下,使用列索引较为高效。列从 1 开始编号。为了获得最大的可移植性,应该按从左到右的顺序读取每行中的结果集列,每列只能读取一次。
对于获取方法,JDBC 驱动程序尝试将底层数据转换为在获取方法中指定的 Java 类型,并返回适当的 Java 值。JDBC 规范有一个表,显示允许的从 SQL 类型到 ResultSet 获取方法所使用的 Java 类型的映射关系。
用作获取方法的输入的列名称不区分大小写。用列名称调用获取方法时,如果多个列具有这一名称,则返回第一个匹配列的值。在生成结果集的 SQL 查询中使用列名称时,将使用列名称选项。对于没有在查询中显式指定的列,最好使用列编号。如果使用列名称,则程序员应该注意保证名称唯一引用预期的列,这可以使用 SQL AS 子句确定
当生成 ResultSet
对象的 Statement
对象关闭、重新执行或用来从多个结果的序列获取下一个结果时,ResultSet
对象将自动关闭。
方法摘要 | |
boolean | absolute(int row) |
void | afterLast() |
void | beforeFirst() |
void | cancelRowUpdates() |
void | clearWarnings() |
void | close() |
void | deleteRow() |
int | findColumn(String columnLabel) |
boolean | first() |
Array | getArray(int columnIndex) |
Array | getArray(String columnLabel) |
InputStream | getAsciiStream(int columnIndex) |
InputStream | getAsciiStream(String columnLabel) |
BigDecimal | getBigDecimal(int columnIndex) |
BigDecimal | getBigDecimal(int columnIndex, int scale) |
BigDecimal | getBigDecimal(String columnLabel) |
BigDecimal | getBigDecimal(String columnLabel, int scale) |
InputStream | getBinaryStream(int columnIndex) |
InputStream | getBinaryStream(String columnLabel) |
Blob | getBlob(int columnIndex) |
Blob | getBlob(String columnLabel) |
boolean | getBoolean(int columnIndex) |
boolean | getBoolean(String columnLabel) |
byte | getByte(int columnIndex) |
byte | getByte(String columnLabel) |
byte[] | getBytes(int columnIndex) |
byte[] | getBytes(String columnLabel) |
Reader | getCharacterStream(int columnIndex) |
Reader | getCharacterStream(String columnLabel) |
Clob | getClob(int columnIndex) |
Clob | getClob(String columnLabel) |
int | getConcurrency() |
String | getCursorName() |
Date | getDate(int columnIndex) |
Date | getDate(int columnIndex, Calendar cal) |
Date | getDate(String columnLabel) |
Date | getDate(String columnLabel, Calendar cal) |
double | getDouble(int columnIndex) |
double | getDouble(String columnLabel) |
int | getFetchDirection() |
int | getFetchSize() |
float | getFloat(int columnIndex) |
float | getFloat(String columnLabel) |
int | getHoldability() |
int | getInt(int columnIndex) |
int | getInt(String columnLabel) |
long | getLong(int columnIndex) |
long | getLong(String columnLabel) |
ResultSetMetaData | getMetaData() |
Reader | getNCharacterStream(int columnIndex) |
Reader | getNCharacterStream(String columnLabel) |
NClob | getNClob(int columnIndex) |
NClob | getNClob(String columnLabel) |
String | getNString(int columnIndex) |
String | getNString(String columnLabel) |
Object | getObject(int columnIndex) |
Object | getObject(int columnIndex, Map<String,Class<?>> map) |
Object | getObject(String columnLabel) |
Object | getObject(String columnLabel, Map<String,Class<?>> map) |
Ref | getRef(int columnIndex) |
Ref | getRef(String columnLabel) |
int | getRow() |
RowId | getRowId(int columnIndex) |
RowId | getRowId(String columnLabel) |
short | getShort(int columnIndex) |
short | getShort(String columnLabel) |
SQLXML | getSQLXML(int columnIndex) |
SQLXML | getSQLXML(String columnLabel) |
Statement | getStatement() |
String | getString(int columnIndex) |
String | getString(String columnLabel) |
Time | getTime(int columnIndex) |
Time | getTime(int columnIndex, Calendar cal) |
Time | getTime(String columnLabel) |
Time | getTime(String columnLabel, Calendar cal) |
Timestamp | getTimestamp(int columnIndex) |
Timestamp | getTimestamp(int columnIndex, Calendar cal) |
Timestamp | getTimestamp(String columnLabel) |
Timestamp | getTimestamp(String columnLabel, Calendar cal) |
int | getType() |
InputStream | getUnicodeStream(int columnIndex) |
InputStream | getUnicodeStream(String columnLabel) |
URL | getURL(int columnIndex) |
URL | getURL(String columnLabel) |
SQLWarning | getWarnings() |
void | insertRow() |
boolean | isAfterLast() |
boolean | isBeforeFirst() |
boolean | isClosed() |
boolean | isFirst() |
boolean | isLast() |
boolean | last() |
void | moveToCurrentRow() |
void | moveToInsertRow() |
boolean | next() |
boolean | previous() |
void | refreshRow() |
boolean | relative(int rows) |
boolean | rowDeleted() |
boolean | rowInserted() |
boolean | rowUpdated() |
void | setFetchDirection(int direction) |
void | setFetchSize(int rows) |
void | updateArray(int columnIndex, Array x) |
void | updateArray(String columnLabel, Array x) |
void | updateAsciiStream(int columnIndex, InputStream x) |
void | updateAsciiStream(int columnIndex, InputStream x, int length) |
void | updateAsciiStream(int columnIndex, InputStream x, long length) |
void | updateAsciiStream(String columnLabel, InputStream x) |
void | updateAsciiStream(String columnLabel, InputStream x, int length) |
void | updateAsciiStream(String columnLabel, InputStream x, long length) |
void | updateBigDecimal(int columnIndex, BigDecimal x) |
void | updateBigDecimal(String columnLabel, BigDecimal x) |
void | updateBinaryStream(int columnIndex, InputStream x) |
void | updateBinaryStream(int columnIndex, InputStream x, int length) |
void | updateBinaryStream(int columnIndex, InputStream x, long length) |
void | updateBinaryStream(String columnLabel, InputStream x) |
void | updateBinaryStream(String columnLabel, InputStream x, int length) |
void | updateBinaryStream(String columnLabel, InputStream x, long length) |
void | updateBlob(int columnIndex, Blob x) |
void | updateBlob(int columnIndex, InputStream inputStream) |
void | updateBlob(int columnIndex, InputStream inputStream, long length) |
void | updateBlob(String columnLabel, Blob x) |
void | updateBlob(String columnLabel, InputStream inputStream) |
void | updateBlob(String columnLabel, InputStream inputStream, long length) |
void | updateBoolean(int columnIndex, boolean x) |
void | updateBoolean(String columnLabel, boolean x) |
void | updateByte(int columnIndex, byte x) |
void | updateByte(String columnLabel, byte x) |
void | updateBytes(int columnIndex, byte[] x) |
void | updateBytes(String columnLabel, byte[] x) |
void | updateCharacterStream(int columnIndex, Reader x) |
void | updateCharacterStream(int columnIndex, Reader x, int length) |
void | updateCharacterStream(int columnIndex, Reader x, long length) |
void | updateCharacterStream(String columnLabel, Reader reader) |
void | updateCharacterStream(String columnLabel, Reader reader, int length) |
void | updateCharacterStream(String columnLabel, Reader reader, long length) |
void | updateClob(int columnIndex, Clob x) |
void | updateClob(int columnIndex, Reader reader) |
void | updateClob(int columnIndex, Reader reader, long length) |
void | updateClob(String columnLabel, Clob x) |
void | updateClob(String columnLabel, Reader reader) |
void | updateClob(String columnLabel, Reader reader, long length) |
void | updateDate(int columnIndex, Date x) |
void | updateDate(String columnLabel, Date x) |
void | updateDouble(int columnIndex, double x) |
void | updateDouble(String columnLabel, double x) |
void | updateFloat(int columnIndex, float x) |
void | updateFloat(String columnLabel, float x) |
void | updateInt(int columnIndex, int x) |
void | updateInt(String columnLabel, int x) |
void | updateLong(int columnIndex, long x) |
void | updateLong(String columnLabel, long x) |
void | updateNCharacterStream(int columnIndex, Reader x) |
void | updateNCharacterStream(int columnIndex, Reader x, long length) |
void | updateNCharacterStream(String columnLabel, Reader reader) |
void | updateNCharacterStream(String columnLabel, Reader reader, long length) |
void | updateNClob(int columnIndex, NClob nClob) |
void | updateNClob(int columnIndex, Reader reader) |
void | updateNClob(int columnIndex, Reader reader, long length) |
void | updateNClob(String columnLabel, NClob nClob) |
void | updateNClob(String columnLabel, Reader reader) |
void | updateNClob(String columnLabel, Reader reader, long length) |
void | updateNString(int columnIndex, String nString) |
void | updateNString(String columnLabel, String nString) |
void | updateNull(int columnIndex) |
void | updateNull(String columnLabel) |
void | updateObject(int columnIndex, Object x) |
void | updateObject(int columnIndex, Object x, int scaleOrLength) |
void | updateObject(String columnLabel, Object x) |
void | updateObject(String columnLabel, Object x, int scaleOrLength) |
void | updateRef(int columnIndex, Ref x) |
void | updateRef(String columnLabel, Ref x) |
void | updateRow() |
void | updateRowId(int columnIndex, RowId x) |
void | updateRowId(String columnLabel, RowId x) |
void | updateShort(int columnIndex, short x) |
void | updateShort(String columnLabel, short x) |
void | updateSQLXML(int columnIndex, SQLXML xmlObject) |
void | updateSQLXML(String columnLabel, SQLXML xmlObject) |
void | updateString(int columnIndex, String x) |
void | updateString(String columnLabel, String x) |
void | updateTime(int columnIndex, Time x) |
void | updateTime(String columnLabel, Time x) |
void | updateTimestamp(int columnIndex, Timestamp x) |
void | updateTimestamp(String columnLabel, Timestamp x) |
boolean | wasNull() |
eg:ResultSet获取查询对象
Connection con = null;
Statement stat = null;
PreparedStatement preparedStat =null;
try {
try {
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2、获得驱动
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/datatest","root","root");
//3、向数据库发送sql语句
String sql = "select name,age from user ";
preparedStat = con.prepareStatement(sql);
ResultSet rs = preparedStat.executeQuery();
while(rs.next()){
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(name+":"+age);
}
}
catch (SQLException e) {
e.printStackTrace();
}finally{
if(null != con)
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(null != stat)
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
九、DatabaseMetaData
public interface DatabaseMetaData extends Wrapper
关于数据库的整体综合信息。
此接口由驱动程序供应商实现,让用户了解 Database Management System (DBMS) 在与驱动程序(基于与其一起使用的 JDBCTM 技术(“JDBC 驱动程序”))相结合时的能力。不同的关系 DBMS 常常支持不同的功能,以不同方式实现这些功能,并使用不同的数据类型。此外,驱动程序可以实现 DBMS 提供的顶级功能。此接口中的方法返回的信息关系到一起工作的特定驱动程序和特定 DBMS 的能力。注意,正如此文档中所使用的那样,术语“数据库”通常既指驱动程序,又指 DBMS。
此接口的用户通常是一个需要发现如何处理底层 DBMS 的工具。对于试图与多个 DBMS 一起使用的应用程序而言尤其如此。例如,一个工具可能使用 getTypeInfo
方法找出可以在 CREATE TABLE
语句中使用的数据类型。或者用户可能调用 supportsCorrelatedSubqueries
方法查看是否可以使用相关子查询,或者调用 supportsBatchUpdates
查看是否可以使用批量更新。
有些 DatabaseMetaData
方法以 ResultSet
对象的形式返回信息列表。常规 ResultSet
方法(比如 getString
和 getInt
)可用于从这些 ResultSet
对象中获取数据。如果给定形式的元数据不可用,则将返回一个空 ResultSet
。对于被定义为由 ResultSet
对象的给定方法所返回的列以外的其他列,可以由 JDBC 驱动程序供应商定义,且必须通过其列标签访问。
有些 DatabaseMetaData
方法使用 String 模式的参数。这些参数都有 fooPattern 这样的名称。在模式 String 中,"%" 表示匹配 0 个或多个字符的任何子字符串,"_" 表示匹配任何一个字符。仅返回匹配搜索模式的元数据项。如果将搜索模式参数设置为 null
,则从搜索中删除参数标准。
eg :通过DatabaseMetaData获取数据库中的各个表信息。
Connection con = null;
Statement stat = null;
try {
try {
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2、获得驱动
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/datatest","root","root");
//3、获取该数据库下的所有表元数据
DatabaseMetaData dbmt = con.getMetaData();
//4、获取各个表信息
ResultSet tableRet = dbmt.getTables(null, "%", "%", new String[]{"TABLE"});
while(tableRet.next()){
//(1)、获取表名
String tableName = (String) tableRet.getObject("TABLE_NAME");
//获取表类型:"TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
String tableType = (String) tableRet.getObject("TABLE_TYPE");
System.out.println("表名:"+tableName+",表类型:"+tableType);
//(2)、列名+该列的数据类型
ResultSet columnRet = dbmt.getColumns(null, "%" ,tableName, "%");
while(columnRet.next()){
String columnName = (String) columnRet.getString("COLUMN_NAME");
String typeName = (String) columnRet.getString("TYPE_NAME");
System.out.println(columnName+"\n"+typeName+"\n");
}
//(3)、获取本表的主键信息
ResultSet keysRet = dbmt.getPrimaryKeys(null, "%", tableName);
while(keysRet.next()){
String pkName = keysRet.getString("COLUMN_NAME");
String keySeQ = keysRet.getString("KEY_SEQ");
System.out.println(pkName+","+keySeQ);
}
}
}catch (SQLException e) {
e.printStackTrace();
}finally{
if(null != con)
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(null != stat)
try {
if(null != con){
con.close();
}
if(null != stat){
stat.close();
}
if(null != tableRet){
tableRet.close();
}
if(null != columnRet){
columnRet.close();
}
if(null != keysRet){
keysRet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
十、ResultSetMetaData
public interface ResultSetMetaData extends Wrapper
可用于获取关于 ResultSet
对象中列的类型和属性信息的对象。以下代码片段创建 ResultSet
对象 rs,创建 ResultSetMetaData
对象 rsmd,并使用 rsmd 查找 rs 有多少列,以及 rs 中的第一列是否可以在 WHERE
子句中使用。
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
boolean b = rsmd.isSearchable(1);
方法摘要 | |
String | getCatalogName(int column) |
String | getColumnClassName(int column) |
int | getColumnCount() |
int | getColumnDisplaySize(int column) |
String | getColumnLabel(int column) |
String | getColumnName(int column) |
int | getColumnType(int column) |
String | getColumnTypeName(int column) |
int | getPrecision(int column) |
int | getScale(int column) |
String | getSchemaName(int column) |
String | getTableName(int column) |
boolean | isAutoIncrement(int column) |
boolean | isCaseSensitive(int column) |
boolean | isCurrency(int column) |
boolean | isDefinitelyWritable(int column) |
int | isNullable(int column) |
boolean | isReadOnly(int column) |
boolean | isSearchable(int column) |
boolean | isSigned(int column) |
boolean | isWritable(int column) |
这个类就是获取ResultSet结果中,数据的元数据库信息,包括表名,表别名,列名,列别名,结果数等等元数据信息
eg:
PreparedStatement ps =null;
ResultSet rs = null;
List lists = null;
try {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaData metadata = rs.getMetaData();
while(rs.next()){
if(lists == null)
lists = new ArrayList();
Object objentity = cls.newInstance();
for(int i = 0 ; i<metadata.getColumnCount();i++){
//获取查询列的列名(如果有别名,取别名)
String colName = metadata.getColumnLabel(i+1);
System.out.println(colName);
Object val = rs.getObject(i+1);
if(null != val){
val = val.toString();
}
Method m = cls.getDeclaredMethod("set"+StringUtils.firstConverToUpper("a")+(i+1), String.class);
m.invoke(objentity, val);
}
lists.add(objentity);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
DBManager.close(con, ps, rs);
}
return lists;
十一、连接池
连接池:就是将Connection对象放入List中,反复重用的过程!
----连接池的初始化:
事先放入多个链接对象
----从连接池中获取对象:
如果池中有可用链接,就将池中最后一个返回,同时,将该链接从池中remove掉,表示正在使用;如果没用可用链接,则创建新的链接。
----关闭链接:
不是真正关闭链接,而是将链接放回池中。
市面上的连接池产品:
DBCP、C3p0、proxool。
为什么使用连接池?
我们知道每次让java应用服务和数据库链接,需要花费大量的时间,若执行一次sql语句,就与数据库链接一次,用完就关闭,这样对于大量的数据库操作而言,会严重影响系统的性能,
下面是自己写的简单数据库连接池:
package dataBaseConnection.sorm.pool;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import dataBaseConnection.sorm.core.DBManager;
import dataBaseConnection.sorm.core.MysqlQuery;
import dataBaseConnection.sorm.entity.Demo;
/**
* @author:zhangfd
* @version:1.0
* @date:2017年7月29日 上午12:54:13
* @description:手写数据库连接池
*/
public class DBConnectionPool {
/**
* 连接池
*/
private static List<Connection> poolLists;
private static final int Pool_max_size = 10;
private static final int Pool_min_size = 5;
public DBConnectionPool() {
super();
}
//提前先把链接放入List集合中
static{
init();
}
public static void init() {
if (null == poolLists) {
poolLists = new ArrayList<Connection>();
}
while (poolLists.size() < Pool_min_size) {
poolLists.add(DBManager.createcon());
}
}
public synchronized static Connection getCon() {
int i = poolLists.size();
if (i >= 1) {
Connection con = poolLists.get(i-1);
poolLists.remove(i-1);
return con;
} else {
return DBManager.getcon();
}
}
public synchronized static void close(Connection con) {
if (poolLists.size() + 1 > Pool_max_size) {
if (null != con) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} else {
if (null != con)
poolLists.add(con);
}
}
public static void main(String[] args) {
test1();// 不使用连接池查询1000次需要花费的时间:8102ms
test2();//使用连接池查询1000吃需要花费的时间是557ms
}
/**
* 测试不使用连接池查询1000次需要花费的时间
*/
public static void test1() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
seleTest();
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime);
}
public static void test2() {
long beginTime = System.currentTimeMillis();
for(int i=0;i<1000;i++){
seleTest();
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime);
}
public static void seleTest(){
String sql = "select * from user,school where school_id=user_id";
List<Demo> lists = new MysqlQuery().queryrows(sql, Demo.class, null);
for (Demo demo : lists) {
System.out.println(demo.getA1() + "===" + demo.getA4() + "===" + demo.getA8() + "===" + demo.getA10());
}
System.out.println(lists.size());
}
}