1、http://jcs.mobile-utopia.com/jcs/6065_DataSourceImpl.java
调试代码
/************************/ /***** Internal API *****/ /************************/ private void debug(String s) { System.out.println(s); }
2、DBUtil
http://jcs.mobile-utopia.com/jcs/5607_DBUtil.java
package com.oreilly.forum.jdbcimpl; import java.io.*; import java.sql.*; import java.util.*; /** * Helper methods for relational database access using JDBC. */ public class DBUtil { // buffer size when reading long strings private static final int BUF_SIZE = 250; // a map of table names to maximum ID numbers private static Map tableToMaxIDMap = new HashMap(); /** * Close a statement and connection. */ public static void close(Statement stmt, Connection con) { if (stmt != null) { try { stmt.close(); } catch (Exception ignored1) { } } if (con != null) { try { // return the connection to the pool putPooledConnection(con); } catch (Exception ignored2) { } } } /** * @return a new Connection to the database. */ public static Connection getConnection(String dbURL) throws SQLException { // get a connection from the pool return getPooledConnection(dbURL); } /** * Close any connections that are still open. The Servlet will * call this method from its destroy() method. */ public static void closeAllConnections() { // empty the connection pool and close all connections emptyPool(); } /** * Store a long text field in the database. For example, a message's * text will be quite long and cannot be stored using JDBC's * setString() method. */ public static void setLongString(PreparedStatement stmt, int columnIndex, String data) throws SQLException { if (data.length() > 0) { stmt.setAsciiStream(columnIndex, new ByteArrayInputStream(data.getBytes()), data.length()); } else { // this 'else' condition was introduced as a bug fix. It was // discovered that the 'setAsciiStream' code shown above // caused MS Access to throw a "function sequence error" // when the string was zero length. This code now works. stmt.setString(columnIndex, ""); } } /** * @return a long text field from the database. */ public static String getLongString(ResultSet rs, int columnIndex) throws SQLException { try { InputStream in = rs.getAsciiStream(columnIndex); if (in == null) { return ""; } byte[] arr = new byte[BUF_SIZE]; StringBuffer buf = new StringBuffer(); int numRead = in.read(arr); while (numRead != -1) { buf.append(new String(arr, 0, numRead)); numRead = in.read(arr); } return buf.toString(); } catch (IOException ioe) { ioe.printStackTrace(); throw new SQLException(ioe.getMessage()); } } /** * Compute a new unique ID. It is assumed that the specified table * has a column named 'id' of type 'long'. It is assumed that * that all parts of the program will use this method to compute * new IDs. * @return the next available unique ID for a table. */ public static synchronized long getNextID(String tableName, Connection con) throws SQLException { Statement stmt = null; try { // if a max has already been retreived from this table, // compute the next id without hitting the database if (tableToMaxIDMap.containsKey(tableName)) { Long curMax = (Long) tableToMaxIDMap.get(tableName); Long newMax = new Long(curMax.longValue() + 1L); tableToMaxIDMap.put(tableName, newMax); return newMax.longValue(); } stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT MAX(id) FROM " + tableName); long max = 0; if (rs.next()) { max = rs.getLong(1); } max++; tableToMaxIDMap.put(tableName, new Long(max)); return max; } finally { // just close the statement close(stmt, null); } } ////////////////////////////////////////////////////////////////// // a rudimentary connection pool private static Stack availableConnections = new Stack(); private static synchronized Connection getPooledConnection(String dbURL) throws SQLException { if (!availableConnections.isEmpty()) { System.out.println("Reusing a connection"); return (Connection) availableConnections.pop(); } else { System.out.println("Creating a connection"); return DriverManager.getConnection(dbURL); } } private static synchronized void putPooledConnection(Connection con) { availableConnections.push(con); } private static synchronized void emptyPool() { while (!availableConnections.isEmpty()) { Connection con = (Connection) availableConnections.pop(); try { con.close(); } catch (SQLException ignored) { } } } ////////////////////////////////////////////////////////////////// }
阅读代码:
A、close(stmt, conn),这种方式释放连接
B、getConnection(String dbURL), dbURL由用户自己去写,可重用性更强;从栈中返回连接,可重用连接
C、setLongString(…),如果要插入的字段过长,就不能使用PrepareedStatement的setString()
D、getLongString()
InputStream in = rs.getAsciiStream(columnIndex);
byte[] arr = new byte[BUF_SIZE]; StringBuffer buf = new StringBuffer(); int numRead = in.read(arr); while (numRead != -1) { buf.append(new String(arr, 0, numRead)); numRead = in.read(arr); } return buf.toString();
当InputStream字符流过长时,不应用String来保存,而是使用StringBuffer
catch (IOException ioe) { ioe.printStackTrace(); throw new SQLException(ioe.getMessage()); }
在catch中捕获了异常,再抛出
E、把数据库连接保存在stack中
private static Stack<Connection> availableConnections = new Stack<Connection>();