日期:2017/11/11

一、JDBC 之 概念

      java database conectivity,是一种用于执行SQL语句的Java API,可以为 多种关系数据库 提供 统一访问接口,它由一组用 Java语言编写的 类和接口 组成。 有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事。换言之,有了 JDBC API,就不必为访问Sybase数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问 Informix 数据库又编写另一个程序等等,程序员只需用 JDBC API 写一个程序就够了, 它可向相应数据库发送SQL调用

    简单地说,JDBC 可做三件事:与数据库建立连接、发送操作数据库的语句 并 处理结果


软件包 java.sql


提供使用 Java

TM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。


接口摘要

Array

SQL 类型 ​​ARRAY​​ 在 Java 编程语言中的映射关系。

Blob

SQL ​​BLOB​​ 值在 JavaTM 编程语言中的表示形式(映射关系)。

CallableStatement

用于执行 SQL 存储过程的接口。

Clob

SQL 类型 ​​CLOB​​ 在 JavaTM 编程语言中的映射关系。

Connection

与特定数据库的连接(会话)。

DatabaseMetaData

关于数据库的整体综合信息。

Driver

每个驱动程序类必须实现的接口。

NClob

SQL ​​NCLOB​​ 类型在 JavaTM 编程语言中的映射。

ParameterMetaData

可用于获取关于 ​​PreparedStatement​​ 对象中每个参数标记的类型和属性信息的对象。

PreparedStatement

表示预编译的 SQL 语句的对象。

Ref

Java 编程语言中 SQL ​​REF​​ 值的映射关系,它是到数据库中的 SQL 结构类型值的引用。

ResultSet

表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

ResultSetMetaData

可用于获取关于 ​​ResultSet​​ 对象中列的类型和属性信息的对象。

RowId

SQL ROWID 值在 Java 编程语言中的表示形式(映射)。

Savepoint

保存点的表示形式,保存点是可以从 ​​Connection.rollback​​ 方法引用的当前事务中的点。

SQLData

该接口用于 SQL 用户定义类型 (UDT) 到 Java 编程语言中类的自定义映射关系。

SQLInput

一个输入流,它包含表示 SQL 结构化类型或 SQL 不同类型的实例的值组成的流。

SQLOutput

用于将用户定义类型的属性写回数据库的输出流。

SQLXML

SQL XML 类型在 JavaTM 编程语言中的映射关系。

Statement

用于执行静态 SQL 语句并返回它所生成结果的对象。

Struct

用于 SQL 结构化类型的 Java 编程语言中的标准映射关系。

Wrapper

在相关实例实际上是代理类时提供获取委托实例能力的 JDBC 类的接口。

 

类摘要

Date

一个包装了毫秒值的瘦包装器 (thin wrapper),它允许 JDBC 将毫秒值标识为 SQL ​​DATE​​值。

DriverManager

管理一组 JDBC 驱动程序的基本服务。

DriverPropertyInfo

用于建立连接的驱动程序属性。

SQLPermission

​SecurityManager​​​ 将用来检查在 applet 中运行的代码何时调用 ​​DriverManager.setLogWriter​​​ 方法或 ​​DriverManager.setLogStream​​(不建议使用)方法的权限。

Time

一个与 ​​java.util.Date​​​ 类有关的瘦包装器 (thin wrapper),它允许 JDBC 将该类标识为 SQL ​​TIME​​ 值。

Timestamp

一个与 ​​java.util.Date​​​ 类有关的瘦包装器 (thin wrapper),它允许 JDBC API 将该类标识为 SQL ​​TIMESTAMP​​ 值。

Types

定义用于标识一般 SQL 类型(称为 JDBC 类型)的常量的类。



二、JDBC 之 常用接口

2.1 Connection接口

应用程序  和 数据库

     Connection接口 - Connection与特定数据库的连接(会话),在连接上下文中执行SQL语句并返回结果。
    - DriverManager的 getConnection() 方法建立在JDBC URL中定义的数据库Connection连接上
      -Mysql
        Connection con = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
      -Oracle
        Connection con = DriverManager.getConnection("jdbc:oracle:thin@host:port/database", "user", "password");

java.sql  接口 Connection


所有超级接口:

​Wrapper​



public interface Connection extends ​​Wrapper​

​ void​

close()​​ 

          立即释放此 ​​Connection​​ 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。

​ Statement​

createStatement()​​ 

          创建一个 ​​Statement​​ 对象来将 SQL 语句发送到数据库。

​ Statement​

createStatement(int resultSetType, int resultSetConcurrency)​​ 

          创建一个 ​​Statement​​​ 对象,该对象将生成具有给定类型和并发性的 ​​ResultSet​​ 对象。

​ Statement​

createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)​​ 

          创建一个 ​​Statement​​​ 对象,该对象将生成具有给定类型、并发性和可保存性的 ​​ResultSet​​ 对象。

​ PreparedStatement​

prepareStatement(String​​ 

          创建一个 ​​PreparedStatement​​ 对象来将参数化的 SQL 语句发送到数据库。

​ PreparedStatement​

prepareStatement(String​​ 

          创建一个默认 ​​PreparedStatement​​ 对象,该对象能获取自动生成的键。

​ PreparedStatement​

prepareStatement(String​​ 

          创建一个能返回由给定数组指定的自动生成键的默认 ​​PreparedStatement​​ 对象。

​ PreparedStatement​

prepareStatement(String​​ 

          创建一个 ​​PreparedStatement​​​ 对象,该对象将生成具有给定类型和并发性的 ​​ResultSet​​ 对象。

​ PreparedStatement​

prepareStatement(String​​ 

          创建一个 ​​PreparedStatement​​​ 对象,该对象将生成具有给定类型、并发性和可保存性的 ​​ResultSet​​ 对象。

​ PreparedStatement​

prepareStatement(String sql, String[] columnNames)​​ 

          创建一个能返回由给定数组指定的自动生成键的默认 ​​PreparedStatement​​ 对象。


2.2 Statement接口

Statement接口用于创建 向数据库传递SQL语句 的对象,提供了 许多操作数据库的方法。用于执行静态 SQL 语句并返回它所生成结果的对象。java.sql 

接口 Statement


所有超级接口:

​Wrapper​


所有已知子接口:

​CallableStatement​​, 

​PreparedStatement​



public interface Statement extends ​​Wrapper​

​ void​

close()​​ 

          立即释放此 ​​Statement​​ 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。

​ boolean​

execute(String​​ 

          执行给定的 SQL 语句,该语句可能返回多个结果。

​ boolean​

execute(String​​ 

          执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序所有自动生成的键都应该可用于获取。

​ boolean​

execute(String​​ 

          执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于获取。

​ boolean​

execute(String sql, String[] columnNames)​​ 

          执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于获取。

​ ResultSet​

executeQuery(String​​ 

          执行给定的 SQL 语句,该语句返回单个 ​​ResultSet​​ 对象。

​ int​

executeUpdate(String​​ 

          执行给定 SQL 语句,该语句可能为 ​​INSERT​​​、​​UPDATE​​​ 或 ​​DELETE​​ 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。

​Connection​

getConnection()​​ 

          获取生成此 ​​Statement​​​ 对象的 ​​Connection​​ 对象。

​ int​

getMaxRows()​​ 

          获取由此 ​​Statement​​​ 对象生成的 ​​ResultSet​​ 对象可以包含的最大行数。

​ ResultSet​

getResultSet()​​ 

          以 ​​ResultSet​​ 对象的形式获取当前结果。




2.3  PreparedStatement 接口

     表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 ​​PreparedStatement​​ 对象中。然后可以使用此对象多次高效地执行该语句。

java.sql  接口 PreparedStatement


所有超级接口:

​Statement​​, 

​Wrapper​


所有已知子接口:

​CallableStatement​




public interface PreparedStatement extends ​​Statement​

​ boolean​

execute()​​ 

          在此 ​​PreparedStatement​​ 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。

​ ResultSet​

executeQuery()​​ 

          在此 ​​PreparedStatement​​​ 对象中执行 SQL 查询,并返回该查询生成的 ​​ResultSet​​ 对象。

​ParameterMetaData​

getParameterMetaData()​​ 

          获取此 ​​PreparedStatement​​ 对象的参数的编号、类型和属性。






2.4  DriverManager 接口

管理一组 JDBC 驱动程序的基本服务。
注:​DataSource​​​ 接口是 JDBC 2.0 API 中的新增内容,它提供了连接到数据源的另一种方法。使用 ​​DataSource​​ 对象是连接到数据源的首选方法。

java.sql 

类 DriverManager


​java.lang.Object​


java.sql.DriverManager



public class DriverManager extends ​​Object​

​static Connection​

getConnection(String​​ 

          试图建立到给定数据库 URL 的连接。

​static Connection​

getConnection(String url, Properties​​ 

          试图建立到给定数据库 URL 的连接。

​static Connection​

getConnection(String url, String user, String​​ 

          试图建立到给定数据库 URL 的连接。

​static Driver​

getDriver(String​​ 

          试图查找能理解给定 URL 的驱动程序。



2.5  ResultSet 接口

     类似于临时表,用于暂存数据库查询操作获得的结果集。表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。
     默认的 ResultSet 对象不可更新,仅有一个向前移动的光标。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更 新的 ResultSet 对象。

java.sql  接口 ResultSet

所有超级接口:

​Wrapper​

所有已知子接口:

​CachedRowSet​​​,  ​​FilteredRowSet​​​,  ​​JdbcRowSet​​​,  ​​JoinRowSet​​​,  ​​RowSet​​​,  ​​SyncResolver​​​,  ​​WebRowSet​


public interface ResultSet extends ​​Wrapper​

​ void​

close()​​ 

          立即释放此 ​​ResultSet​​ 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。

​ Array​

getArray(int columnIndex)​​ 

          以 Java 编程语言中 ​​Array​​​ 对象的形式获取此 ​​ResultSet​​ 对象的当前行中指定列的值。

​ Array​

getArray(String​​ 

          以 Java 编程语言中 ​​Array​​​ 对象的形式获取此 ​​ResultSet​​ 对象的当前行中指定列的值。

​ Statement​

getStatement()​​ 

          获取生成此 ​​ResultSet​​​ 对象的 ​​Statement​​ 对象。

​ boolean​

next()​​ 

          将光标从当前位置向前移一行。



三、JDBC 之 代码讲解

(1)通用形式:

package srevletTest;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletMySQL extends HttpServlet{

@SuppressWarnings("null")
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("in doGet()... hahaha");
String user = "root";
String password = "";
String url = "jdbc:mysql://localhost:3306/test";
String driver = "com.mysql.jdbc.Driver";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
PrintWriter out = response.getWriter();
out.println("<table border=1>");
out.println("<tr><td>Contend:</td></tr>");
try{
System.out.println("222 in doGet()... hahaha");
Class. forName(driver);//加载驱动,Class.forName
System.out.println("333 driver successfully... hahaha");
// conn = DriverManager.getConnection(url, user, password);//建立连接
conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=root&password=");
System.out.println("444 connection successfully...hahaha");
//内存泄露
// rs = stmt.executeQuery("select * from classtable");
rs = stmt.executeQuery("USE TEST");
rs = stmt.executeQuery("select name from classtable");
System.out.println("select name from classtable :");
// Collection c = new ArrayList();
while(rs.next()){
System.out.println("show result...kkkk");
out.println("<tr>");
out.println("<td>" + rs.getString("name") + "</td>");
out.println("</tr>");
System.out.println("After**");
// int a1 = rs.getInt(1);
// String a2 = rs.getString(2);
// String a3 = rs.getString(3);
// int a4 = rs.getInt(4);
// String a5 = rs.getString(5);
// int a6 = rs.getInt(6);
// System.out.println(a1+" "+a2 +" "+a3 +" "+a4+" "+a5+" "+a6);
// c.add(a1);c.add(a2);c.add(a3);c.add(a4);c.add(a5);c.add(a6);
// System.out.println(c);
// Iterator it = c.iterator();
// while(it.hasNext()){
// out.println("<tr>");
// out.print("<td>");
// out.print(it.next());
// out.print("</td>");
// out.println("</tr>");
// }
}
}catch(SQLException | ClassNotFoundException e1){
e1. printStackTrace();
}finally{
try{
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
}catch(SQLException e){
System.out.println(e. getMessage());
}
}
}

@Override
public void destroy() {
super.destroy();
try{
DriverManager.deregisterDriver(DriverManager.getDrivers().nextElement());
}catch(Exception e){
e.printStackTrace();
}
}



}


(2)javabean封装好后,在继承servlet类后进行返回调用:



package srevletTest;
import java.sql.*;
public class DB {
public static Connection getConn(){
Connection conn = null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=root&password=");
}catch(ClassNotFoundException e){
e.printStackTrace();
}catch(SQLException e ){
e.printStackTrace();
}
return conn;
}

public static Statement getStatement(Connection conn){
Statement stmt = null;
try{
if(conn != null){
stmt = conn.createStatement();
}
} catch (SQLException e){
e.printStackTrace();
}
return stmt;
}

public static ResultSet getResultSet(Statement stmt,String sql){
ResultSet rs = null;
try {
if (stmt != null){
rs = stmt.executeQuery(sql);
}
} catch (SQLException e){
e.printStackTrace();
}
return rs;
}

public static void closeConn(Connection conn){
try{
if(conn != null){
conn.close();
conn = null;
}
} catch (SQLException e){
e.printStackTrace();
}
}

public static void closeStatement(Statement stmt){
try{
if(stmt != null){
stmt.close();
}
} catch(SQLException e){
e.printStackTrace();
}
}

public static void closeRs(ResultSet rs){
try {
if(rs != null){
rs.close();
rs = null;
}
} catch(SQLException e){
e.printStackTrace();
}
}

}


package srevletTest;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DBtest extends HttpServlet{

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("in doGet()!!");
PrintWriter out = response.getWriter();
Connection conn = DB.getConn();
Statement stmt = DB.getStatement(conn);
ResultSet rs = DB.getResultSet(stmt, "SELECT * FROM classtable");
out.println("<table border=1>");
out.println("<tr><td>Contend:</td></tr>");
try{
while (rs.next()){
out.println("<tr>");
out.println("<td>" + rs.getString("name") + "</td>");
out.println("</tr>");
}
}catch (SQLException e){
e.printStackTrace();
}finally{
DB.closeConn(conn);
DB.closeRs(rs);
DB.closeStatement(stmt);
System.out.println("allover..");
}
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("in doPost()!!");
doGet(req,resp);
}

@Override
public void destroy() {
System.out.println("destory()...");
}

@Override
public void init() throws ServletException {
System.out.println("init()...");
}





}


PS:一、 Class.forName 有什么意思?

答: (1)这里面涉及了java的重要特性 --- 反射机制:能够 在运行时对类进行装载 或 运行时动态的创建类的对象。在反射机制中,Class 是非常重要的类;

java.lang
类 Class<T>
      java.lang.Object
      继承者 java.lang.Class<T>


​static Class<?>​

forName(String​​ 

          返回与带有给定字符串名的类或接口相关联的 ​​Class​​ 对象。


      (2)因此,创建对象处理new一个,还能反射机制创建。

见下例子:


package com.reflection;

class Base{
public void f(){
System.out.println("Base");
}
}

class Sub extends Base{
public void f(){
System.out.println("Sub");
}
}

public class ReflectionTest {
public static void main(String[] args){
try{
Class c = Class. forName("Sub");
//报错:没有为类型 Class 定义方法 f()
Base b = (Base) c.newInstance();
b.f();
}catch (Exception e){
e.printStackTrace();
}

}

}


输出结果(理论上):


Sub