• java jdbc4.0


    Java SE 6 新特性: Java DB 和 JDBC 4.0

    http://www.ibm.com/developerworks/cn/java/j-lo-jse65/

    JDBC 4.0:新功能,新 API

    如果说上一章介绍了 Java 6 中的一个新成员,它本来就存在,但是没有被加入进 JDK。那么这一章,我们将关注在 JDBC 4.0 中又增加了哪些新功能以及与之相对应的新 API。

    自动加载驱动

    在 JDBC 4.0 之前,编写 JDBC 程序都需要加上以下这句有点丑陋的代码:


    清单 7. 注册 JDBC 驱动

                    
    Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
    

    Java.sql.DriverManager 的内部实现机制决定了这样代码的出现。只有先通过 Class.forName 找到特定驱动的 class 文件,DriverManager.getConnection 方法才能顺利地获得 Java 应用和数据库的连接。这样的代码为编写程序增加了不必要的负担,JDK 的开发者也意识到了这一点。从 Java 6 开始,应用程序不再需要显式地加载驱动程序了,DriverManager 开始能够自动地承担这项任务。作为试验,我们可以将 清单 1 中的相关代码删除,重新编译后在 JRE 6.0 下运行,结果和原先的程序一样。

    好 奇的读者也许会问,DriverManager 为什么能够做到自动加载呢?这就要归功于一种被称为 Service Provider 的新机制。熟悉 Java 安全编程的程序员可能对其已经是司空见惯,而它现在又出现在 JDBC 模块中。JDBC 4.0 的规范规定,所有 JDBC 4.0 的驱动 jar 文件必须包含一个 java.sql.Driver ,它位于 jar 文件的 META-INF/services 目录下。这个文件里每一行便描述了一个对应的驱动类。其实,编写这个文件的方式和编写一个只有关键字(key)而没有值(value)的 properties 文件类似。同样地,‘#’之后的文字被认为是注释。有了这样的描述,DriverManager 就可以从当前在 CLASSPATH 中的驱动文件中找到,它应该去加载哪些类。而如果我们在 CLASSPATH 里没有任何 JDBC 4.0 的驱动文件的情况下,调用 清单 8 中的代码会输出一个 sun.jdbc.odbc.JdbcOdbcDriver 类型的对象。而仔细浏览 JDK 6 的目录,这个类型正是在 %JAVA_HOME%/jre/lib/resources.jar 的 META-INF/services 目录下的 java.sql.Driver 文件中描述的。也就是说,这是 JDK 中默认的驱动。而如果开发人员想使得自己的驱动也能够被 DriverManager 找到,只需要将对应的 jar 文件加入到 CLASSPATH 中就可以了。当然,对于那些 JDBC 4.0 之前的驱动文件,我们还是只能显式地去加载了。


    清单 8. 罗列本地机器上的 JDBC 驱动

                    
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    
    while(drivers.hasMoreElements()) {
        System.out.println(drivers.nextElement());
    }
    

    RowId

    熟悉 DB2、Oracle 等大型 DBMS 的人一定不会对 ROWID 这个概念陌生:它是数据表中一个“隐藏”的列,是每一行独一无二的标识,表明这一行的物理或者逻辑位置。由于 ROWID 类型的广泛使用,Java SE 6 中新增了 java.sql.RowId 的数据类型,允许 JDBC 程序能够访问 SQL 中的 ROWID 类型。诚然,不是所有的 DBMS 都支持 ROWID 类型。即使支持,不同的 ROWID 也会有不同的生命周期。因此使用 DatabaseMetaData.getRowIdLifetime 来判断类型的生命周期不失为一项良好的实践经验。我们在 清单 1 的程序获得连接之后增加以下代码,便可以了解 ROWID 类型的支持情况。


    清单 9. 了解 ROWID 类型的支持情况

                    
    DatabaseMetaData meta = conn.getMetaData();
    System.out.println(meta.getRowIdLifetime());
    

    Java SE 6 的 API 规范中,java.sql.RowIdLifetime 规定了 5 种不同的生命周期:ROWID_UNSUPPORTEDROWID_VALID_FOREVERROWID_VALID_OTHERROWID_VALID_SESSIONROWID_VALID_TRANSACTION 。从字面上不难理解它们表示了不支持 ROWID、ROWID 永远有效等等。具体的信息,还可以参看相关的 JavaDoc。读者可以尝试着连接 Derby 进行试验,会发现运行结果是 ROWID_UNSUPPORTED ,即 Derby 并不支持 ROWID。

    既然提供了新的数据类型,那么一些相应的获取、更新数据表内容的新 API 也在 Java 6 中被添加进来。和其它已有的类型一样,在得到 ResultSet 或者 CallableStatement 之后,调用 get/set/update 方法得到/设置/更新 RowId 对象,示例的代码如 清单 10 所示。


    清单 10. 获得/设置 RowId 对象

                    
    // Initialize a PreparedStatement
    PreparedStatement pstmt = connection.prepareStatement(
        "SELECT rowid, name, score FROM hellotable WHERE rowid = ?");
    // Bind rowid into prepared statement. 
    pstmt.setRowId(1, rowid);
    // Execute the statement
    ResultSet rset = pstmt.executeQuery(); 
    // List the records
    while(rs.next()) {
     	RowId id = rs.getRowId(1); // get the immutable rowid object
     	String name = rs.getString(2);
      	int score = rs.getInt(3);
    }
    

    鉴于不同 DBMS 的不同实现,RowID 对象通常在不同的数据源(datasource)之间并不是可移植的。因此 JDBC 4.0 的 API 规范并不建议从连接 A 取出一个 RowID 对象,将它用在连接 B 中,以避免不同系统的差异而带来的难以解释的错误。而至于像 Derby 这样不支持 RowId 的 DBMS,程序将直接在 setRowId 方法处抛出 SQLFeatureNotSupportedException

    SQLXML

    SQL:2003 标准引入了 SQL/XML,作为 SQL 标准的扩展。SQL/XML 定义了 SQL 语言怎样和 XML 交互:如何创建 XML 数据;如何在 SQL 语句中嵌入 XQuery 表达式等等。作为 JDBC 4.0 的一部分,Java 6 增加了 java.sql.SQLXML 的类型。JDBC 应用程序可以利用该类型初始化、读取、存储 XML 数据。java.sql.Connection.createSQLXML 方法就可以创建一个空白的 SQLXML 对象。当获得这个对象之后,便可以利用 setStringsetBinaryStreamsetCharacterStream 或者 setResult 等方法来初始化所表示的 XML 数据。以 setCharacterStream 为例,清单 11 表示了一个 SQLXML 对象如何获取 java.io.Writer 对象,从外部的 XML 文件中逐行读取内容,从而完成初始化。


    清单 11. 利用 setCharacterStream 方法来初始化 SQLXML 对象

                    
    SQLXML xml = con.createSQLXML();
    Writer writer = xml.setCharacterStream();
    BufferedReader reader = new BufferedReader(new FileReader("test.xml"));
    String line= null;
    while((line = reader.readLine() != null) {
          writer.write(line);
    } 
    

    由于 SQLXML 对象有可能与各种外部的资源有联系,并且在一个事务中一直持有这些资源。为了防止应用程序耗尽资源,Java 6 提供了 free 方法来释放其资源。类似的设计在 java.sql.ArrayClob 中都有出现。

    至于如何使用 SQLXML 与数据库进行交互,其方法与其它的类型都十分相似。可以参照 RowId 一节 中的例子在 Java SE 6 的 API 规范中找到 SQLXML 中对应的 get/set/update 方法构建类似的程序,此处不再赘述。

    SQLExcpetion 的增强

    在 Java SE 6 之前,有关 JDBC 的异常类型不超过 10 个。这似乎已经不足以描述日渐复杂的数据库异常情况。因此,Java SE 6 的设计人员对以 java.sql.SQLException 为根的异常体系作了大幅度的改进。首先,SQLException 新实现了 Iterable<Throwable> 接口。清单 12 实现了 清单 1 程序的异常处理机制。这样简洁地遍历了每一个 SQLException 和它潜在的原因(cause)。


    清单 12. SQLException 的 for-each loop

                    
    // Java 6 code
    catch (Throwable e) {
       if (e instanceof SQLException) {
           for(Throwable ex : (SQLException)e ){
                System.err.println(ex.toString());
            }
        }
    } 
    

    此外,图 4 表示了全部的 SQLException 异常体系。除去原有的 SQLException 的子类,Java 6 中新增的异常类被分为 3 种:SQLReoverableExceptionSQLNonTransientExceptionSQLTransientException 。在 SQLNonTransientExceptionSQLTransientException 之下还有若干子类,详细地区分了 JDBC 程序中可能出现的各种错误情况。大多数子类都会有对应的标准 SQLState 值,很好地将 SQL 标准和 Java 6 类库结合在一起。


    图 4. SQLException 异常体系
    图 4. SQLException 异常体系

    在众多的异常类中,比较常见的有 SQLFeatureNotSupportedException ,用来表示 JDBC 驱动不支持某项 JDBC 的特性。例如在 Derby 下运行 清单 10 中的程序,就可以发现 Derby 的驱动并不支持 RowId 的特性。另外值得一提的是,SQLClientInfoException 直接继承自 SQLException,表示当一些客户端的属性不能被设置在一个数据库连接时所发生的异常。




    回页首

    小结:更多新特性与展望

    在本文中,我们已经向读者介绍了 Java SE 6 中 JDBC 最重要的一些新特性:它们包括嵌在 JDK 中的 Java DB (Derby)和 JDBC 4.0 的一部分。当然,还有很多本文还没有覆盖到的新特性。比如增加了对 SQL 语言中 NCHARNVARCHARLONGNVARCHARNCLOB 类型的支持;在数据库连接池的环境下为管理 Statement 对象提供更多灵活、便利的方法等。

    此 外,在 Java SE 6 的 beta 版中,曾经将 Annotation Query 的特性包含进来。这项特性定义了一系列 Query 和 DataSet 接口,程序员可以通过撰写一些 Annotation 来自定义查询并获得定制的数据集结果。但是,由于这一特性的参考实现最终不能满足 JDK 的质量需求,Sun 公司忍痛割爱,取消了在 Java SE 6 中发布其的计划。我们有理由相信,在以后的 JDK 版本中,这一特性以及更多新的功能将被包含进来,利用 Java 语言构建数据库的应用也会变得更为自然、顺畅。

    参考资料

    jdbc 连接数据库大全

    http://www.javaresearch.org/article/51200.htm

    Class.forName - 加载数据库驱动程序

    //access数据库直连用ODBC的 

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
                String url="jdbc:odbc:Driver={MicroSoft Access Driver
                (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
                Connection conn = DriverManager.getConnection(url,"","");
                Statement stmtNew=conn.createStatement() ; 

    //Java DB Derby


    Class.forName("org.apache.derby.jdbc.ClientDriver");
    java.sql.DriverManager.getConnection("jdbc:derby://localhost:1527/myeclipse","classiccars","classiccars");

    //连接oracle数据库
    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    String url="jdbc:oracle:thin:@localhost:1521:orcl";      //orcl为你的数据库SID

    //连接SQL Server数据库
    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=TestDB"; //TestDB为你的数据库名

    //连接DB2数据库
    Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
    String url="jdbc:db2://localhost:5000/TestDB";          //TestDB为你的数据库名


    JDBC URL :jdbc:db2://tdurden:50000/SAMPLE
    Driver Class field: com.ibm.db2.jcc.DB2Driver  

    //连接Informix数据库
    Class.forName("com.informix.jdbc.IfxDriver").newInstance();
    String url="jdbc:informix-sqli://localhost:1533/TestDB:INFORMIXSERVER=myserver");

    //连接Sybase数据库
    Class.forName("com.sybase.jdbc.SybDriver").newInstance();
    String url="jdbc:sybase:Tds:localhost:5007/TestDB";
    Properties sysProps=System.getProperties();
    SysProps.put("user","asima");
    SysProps.put("password","admin");

    //连接MySQL数据库
    Class.forName("org.gjt.mm.mysql.Driver").newInstance();
    String url="jdbc:mysql://localhost/TestDB?user=asima&password=admin&useUnicode=true&

    characterEncoding=8859_1"

    Class.forName("com.mysql.jdbc.Driver").netInstance();

    String url = "jdbc:mysql://localhost/ssh?user=root&password=admin&userUnicode=true&characterEncoding=UTF-8";   //ssh 为数据库名

    //连接PostgreSQL数据库
    Class.forName("org.postgresql.Driver").newInstance();
    String url="jdbc:postgresql://localhost/TestDB";

    //使用JDBC-ODBC桥
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    String url="jdbc:odbc:TestOdbcName";

    String user="asima";
    String password="admin";

    Connection conn=DriverManager.getConnection(url,user,password);    //与DBMS建立连接
    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
    String sql="select * from TestTable";
    ResultSet rs=stmt.executeQuery(sql);
    while (rs.next())
    {
        ......
    }
    rs.close();
    stmt.close();
    conn.close();

    Oracle.java

    package com.javaeye.lindows.database;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Oracle {
    
    	/**
    	 * @author Lindows
    	 */
    	private static Connection conn = null;
    	private static Statement stmt = null;
    	private static ResultSet rs = null;
    
    	public static void main(String[] args) {
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    			conn = DriverManager.getConnection(
    					"jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
    			System.out.println("conn ok...");
    			stmt = conn.createStatement();
    			rs = stmt.executeQuery("select * from dept");
    			while (rs.next()) {
    				String deptno = rs.getString(1);
    				String dname = rs.getString(2);
    				String loc = rs.getString(3);
    				System.out.println("\t部门编号:" + deptno + "     \t部门名称:" + dname
    						+ "    \t地点:" + loc);
    			}
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (rs != null) {
    					rs.close();
    				}
    				if (ps != null) {
    					stmt.close();
    				}
    				if (conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e2) {
    				e2.printStackTrace();
    			}
    		}
    
    	}
    }
    

    sdfsadfasdf

    oracle.java 补充

    finally {
    			try {
    				if (rs != null) {
    					rs.close();
    
    				}
    			} catch (Exception e) {
    
    //这里放可以log类打印到后台
    			}
    			try {
    				if (ps != null) {
    					ps.close();
    				}
    			} catch (Exception e) {
    //这里放可以log类打印到后台
    			}
    			try {
    				closeConnection();
    			} catch (SQLException e1) {
    //这里放可以log类打印到后台
    			}
    		}
     

    sdfsdaf

    Mysql.java

    package com.lindows.db;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Mysql {
    
    	/**
    	 * @param args
    	 */
    	public static Connection getConn() {
    		Connection conn = null;
    		String driverName = "com.mysql.jdbc.Driver";
    		String username = "root";
    		String password = "";
    		String dbName = "ssh";
    		String url = "jdbc:mysql://127.0.0.1:3306/" + dbName + "?user="
    				+ username + "&password" + password;
    		try {
    			Class.forName(driverName).newInstance();
    			System.out.println("[创建驱动连接实例]>>>" + driverName);
    			conn = DriverManager.getConnection(url);
    			System.out.println();
    			System.out.println("[得到实例连接URL]>>>" + url+"\n");
    		} catch (Exception e) {
    			System.out.println("db conn false");
    			e.printStackTrace();
    		}
    		return conn;
    	}
    
    	public static void main(String[] args) {
    		try {
    			System.out.println("begin...");
    			Statement stmt = Mysql.getConn().createStatement();
    			System.out.println("[构造statement]>>>" + stmt + "\nover...\n");
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		// 第二种:直接连接
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    			DriverManager.getConnection("jdbc:mysql://localhost:3306/ssh",
    					"root", "");
    			System.out.println("ok");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    tbl_user.sql

    -- Create table
    create table TBL_USER
    (
      TBL_ID       NUMBER not null,
      TBL_USERNAME VARCHAR2(20),
      TBL_PASSWORD VARCHAR2(20)
    )
    tablespace USERS
      pctfree 10
      pctused 40
      initrans 1
      maxtrans 255
      storage
      (
        initial 64K
        minextents 1
        maxextents unlimited
      );
    -- Create/Recreate primary, unique and foreign key constraints 
    alter table TBL_USER
      add constraint PK_UID primary key (TBL_ID)
      using index 
      tablespace SYSTEM
      pctfree 10
      initrans 2
      maxtrans 255
      storage
      (
        initial 12K
        next 12K
        minextents 1
        maxextents 249
        pctincrease 50
      );
    
     

    DbcpUtil.java

    package com.lindows.db;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import org.apache.commons.dbcp.BasicDataSource;
    
    import com.lindows.vo.UserBean;
    
    public class DbcpUtil {
    
    	/**
    	 * @param args
    	 * @author Lindows
    	 */
    	private static BasicDataSource dataSource;
    	private static Connection conn = null;
    	private static Statement stmt = null;
    	private static PreparedStatement pstmt = null;
    	private static ResultSet rSet = null;
    	static {
    		dataSource = new BasicDataSource();
    		dataSource.setMaxActive(10);
    		dataSource.setMinIdle(1);
    		dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
    		dataSource.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:oracle9i");
    		dataSource.setUsername("scott");
    		dataSource.setPassword("tiger");
    	}
    
    	public Connection getConnection() {
    		try {
    			return dataSource.getConnection();
    		} catch (SQLException e) {
    			e.printStackTrace();
    			return null;
    		}
    	}
    
    	// 单独写方法关闭Connection
    	public void closeConnection(Connection conn) {
    		try {
    			conn.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    
    	// 传参RPC,然后需要一起关闭
    	public void releaseRPC(ResultSet rSet, PreparedStatement pstmt,
    			Connection conn) throws Exception {
    		if (rSet != null) {
    			rSet.close();
    		}
    		if (pstmt != null) {
    			pstmt.close();
    		}
    		if (conn != null) {
    			conn.close();
    		}
    	}
    
    	// 传参RSC,然后需要一起关闭
    	public void releaseRSC(ResultSet rSet, Statement stmt, Connection conn)
    			throws Exception {
    		if (rSet != null) {
    			rSet.close();
    		}
    		if (stmt != null) {
    			stmt.close();
    		}
    		if (conn != null) {
    			conn.close();
    		}
    	}
    
    	// 可以关闭其中任意一个传参
    	public static void release(Object object) {
    		try {
    			if (object instanceof ResultSet) {
    				((ResultSet) object).close();
    			} else if (object instanceof Statement) {
    				((Statement) object).close();
    			} else if (object instanceof PreparedStatement) {
    				((PreparedStatement) object).close();
    			} else if (object instanceof Connection) {
    				((Connection) object).close();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	//tbl_user.sql
    	public void findUser(int tbl_id, String username) throws Exception {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		ResultSet rSet = null;
    		String sql = "SELECT * FROM tbl_user t WHERE t.tbl_id = ? and t.tbl_username = ?";
    		conn = dataSource.getConnection();
    		pstmt = conn.prepareStatement(sql);
    		pstmt.setInt(1, tbl_id); //第一个问号索引
    		pstmt.setString(2, username);
    		rSet = pstmt.executeQuery();
    		while (rSet.next()) {
    			System.out.println(rSet.getString(1));
    			System.out.println(rSet.getString(2));
    		}
    	}
    
    	public static void main(String[] args) {
    		DbcpUtil dbUtil = new DbcpUtil();
    		try {
    			dbUtil.findUser(1, "tt");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
     

    数据库连接关闭顺序

    http://topic.csdn.net/t/20040503/15/3029992.html

    1. rs.close();        //java.sql.ResultSet
    2. rs = null; 
    3. pstmt.close();  //java.sql.PrepareStatement
    4. conn.close(); //java.sql.Connection

    连接池原理图.rar

    http://dl.iteye.com/topics/download/9f84c62e-20c3-3194-94c6-7dfdc0def9b8

    end

  • 相关阅读:
    待你长发及腰
    《线段树》讲稿
    Codeforces #Round 376 F 题解
    包裹快递 题解
    Codeforces #Round 376 部分题解
    圆圈舞蹈 题解
    奶牛晒衣服 题解
    BZOJ 1034 题解
    BZOJ 1045 题解
    BZOJ 1054 题解
  • 原文地址:https://www.cnblogs.com/lindows/p/14390626.html
Copyright © 2020-2023  润新知