欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jdbc操作大观园

程序员文章站 2022-07-13 17:02:12
...
最近公司使用jdbc和mybatis比较多,于是自己试着写了一个方便的类库打包,便于自己使用。高手指教。
package org.liufei.jweb.sql.util;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.log4j.Logger;

/**
 * JDBC事物工具。
 * 
 * @author 刘飞
 * 
 */
public abstract class JdbcTransaction<T> {
	private Logger logger = Logger.getLogger(JdbcTransaction.class);

	private Connection conn;
	private boolean isCloseConnection = false;

	/**
	 * 自动控制的事物块。
	 * 
	 * @param conn
	 *            数据库连接
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接, 默认为false不关闭。
	 */
	public JdbcTransaction(Connection conn, boolean isCloseConnection) {
		super();
		this.conn = conn;
		this.isCloseConnection = isCloseConnection;
	}

	public final T doInTransaction() throws SQLException {
		T result = null;

		boolean autoCommit = false;

		if (this.conn != null) {
			try {

				/**
				 * 保存Connection原始属性
				 */
				autoCommit = this.conn.getAutoCommit();

				/**
				 * 在本代码快里设置Connection非自动提交
				 */
				if (this.conn.getAutoCommit()) {
					this.conn.setAutoCommit(false);
				}

				/**
				 * 执行事务代码块
				 */
				result = this.doInTransaction(this.conn);

				/**
				 * 提交事务
				 */
				this.conn.commit();

				/**
				 * 恢复Connection的原始属性, 以免对其他代码造成影响。
				 */
				this.conn.setAutoCommit(autoCommit);

			} catch (SQLException e) {
				logger.error("事物代码块异常 ", e);
				try {
					this.conn.rollback();
				} catch (SQLException e1) {
					logger.error("事物回滚时异常 ", e);
					throw new SQLException("事物回滚时异常 : "
							+ e1.getLocalizedMessage());
				}
				throw new SQLException("事物代码块异常 : " + e.getLocalizedMessage());
			} finally {
				try {
					this.conn.setAutoCommit(autoCommit);
				} catch (SQLException e) {
					logger.error("恢复Connection自动提交属性异常 ", e);
					throw new SQLException("恢复Connection自动提交属性异常 : \n"
							+ e.getLocalizedMessage());

				}
				if (this.isCloseConnection) {
					try {
						this.conn.close();
						this.conn = null;
					} catch (SQLException e) {
						logger.error("数据库连接关闭时 ", e);
						throw new SQLException("数据库连接关闭时 : "
								+ e.getLocalizedMessage());
					}
				}
			}
		}

		return result;
	}

	protected abstract T doInTransaction(Connection conn) throws SQLException;
}

package org.liufei.jweb.sql.util;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.liufei.jweb.sql.callback.Callback;
import org.liufei.jweb.sql.callback.ConnectionCallback;
import org.liufei.jweb.sql.callback.ResultSetCallback;
import org.liufei.jweb.sql.callback.SqlCallback;

/**
 * 
 * @author 刘飞
 *
 */
public class JdbcUser {

	public static <T> T executeConnectionQueryCallback(final Connection conn, final String sql, ResultSetCallback<T> callback) throws SQLException {
		return new SqlCallback<T, ResultSet>(){

			public T doInSQLCallback(String sql, Callback<T, ResultSet> callback)
					throws SQLException {
				return callback.doInSql(JdbcUtil.executeQuery(conn, sql));
			}}
		.doInSQLCallback(sql, callback) ;
	}
	
	public static <T> T executeSQLDML(final Connection conn, boolean isCloseConnection, final ConnectionCallback<T> callback) throws SQLException {
		return new JdbcTransaction<T>(conn, isCloseConnection){

			@Override
			public T doInTransaction(Connection conn) throws SQLException {
				return callback.doInSql(conn);
			}}
		.doInTransaction();
	}
}


package org.liufei.jweb.sql.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.liufei.jweb.sql.callback.ConnectionCallback;

/**
 * jdbc操作工具。
 * 
 * @author 刘飞
 * 
 */
public class JdbcUtil {
	private static final Logger logger = Logger.getLogger(JdbcUtil.class);

	/**
	 * 用于执行对数据库的查询。
	 * 
	 * @param conn
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	public static ResultSet executeQuery(Connection conn, String sql)
			throws SQLException {
		if (conn != null && sql != null) {
			if(isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY(conn) && isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(conn)) {
				return conn.prepareStatement(sql,
						ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_READ_ONLY).executeQuery();
			}
			else {
				return conn.prepareStatement(sql).executeQuery();
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}
	
	/**
	 * 
	 * @param <T>
	 * @param conn
	 * @param callback
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return
	 * @throws SQLException 
	 */
	public static <T> T executeSQL(final Connection conn, final ConnectionCallback<T> callback, boolean isCloseConnection) throws SQLException {
		return (T) new JdbcTransaction<T>(conn, isCloseConnection){

			@Override
			public T doInTransaction(Connection conn) throws SQLException {
				return callback.doInSql(conn);
			}}
		.doInTransaction();
	}

	/**
	 * 用于执行对数据库的修改更新和删除。
	 * 
	 * @param conn
	 * @param sql
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return
	 * @throws SQLException
	 */
	public static int executeSQLDML(Connection conn, final String sql,
			boolean isCloseConnection) throws SQLException {
		if (conn != null && sql != null) {

			JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
					conn, isCloseConnection) {

				@Override
				public Integer doInTransaction(Connection conn)
						throws SQLException {
					int result = 0 ;
					if(isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_UPDATABLE(conn) && isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(conn)) {
						/**
						 * 执行数据库更新
						 */
						result = conn.prepareStatement(sql,
								ResultSet.TYPE_SCROLL_INSENSITIVE,
								ResultSet.CONCUR_UPDATABLE).executeUpdate();
					}
					else {
						/**
						 * 执行数据库更新
						 */
						result = conn.prepareStatement(sql).executeUpdate();
					}
					return result;
				}
			};

			return jdbcTransaction.doInTransaction();
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}

	/**
	 * PreparedStatement 执行批处理。
	 * 
	 * @param conn
	 * @param batchSql
	 *            批量更新SQL
	 * @param parameters
	 *            二维参数列表, 用于注入SQL中
	 * @param times
	 *            每多少条执行一次更新
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return 返回此批处理共影响的数据条数。
	 * @throws SQLException
	 */
	public static int executePreparedStatementSQLBatch(Connection conn,
			final String batchSql, final Object[][] parameters,
			final int times, final boolean isCloseConnection) throws SQLException {
		if (conn != null && batchSql != null) {

			if (batchSql.length() > 0) {
				if(isSupportsBatchUpdates(conn)) {
					JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
							conn, isCloseConnection) {

						@Override
						public Integer doInTransaction(Connection conn)
								throws SQLException {
							int result = 0;
							/**
							 * 执行批量操作
							 */
							PreparedStatement pstmt = conn
									.prepareStatement(batchSql);

							int i = 1;
							for (Object[] params : parameters) {
								int j = 1;
								for (Object param : params) {
									pstmt.setObject(j, param);
									j++;
								}

								if (i % times == 0) {
									int[] rs = pstmt.executeBatch();
									for (int k : rs) {
										result += k;
									}
								}

								i++;
							}

							release(null, pstmt, null, false) ;
							
							return result;
						}
					};

					return jdbcTransaction.doInTransaction();
				}
				else {
					throw new RuntimeException("this database does not supports batch updates.") ;
				}
			} else {
				return 0;
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}

	/**
	 * Statement执行批处理。
	 * 
	 * @param conn
	 * @param batchSql
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return 返回此批处理共影响的数据条数。
	 * @throws SQLException
	 */
	public static int executeStatementSQLBatch(Connection conn,
			final String[] batchSql, final int times, final boolean isCloseConnection)
			throws SQLException {
		if (conn != null && batchSql != null) {

			if (batchSql.length > 0) {
				if(isSupportsBatchUpdates(conn)) {
					JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
							conn, isCloseConnection) {

						@Override
						public Integer doInTransaction(Connection conn)
								throws SQLException {

							int rs = 0;
							/**
							 * 执行批量操作
							 */
							Statement stmt = conn.createStatement();
							int k = 0 ;
							for (String sql : batchSql) {
								if (sql.trim().length() > 0) {
									stmt.addBatch(sql);
								}
								
								if(k % times == 0) {
									int[] result = stmt.executeBatch();
									for (int i : result) {
										rs += i;
									}
								}
								
							}

							release(null, stmt, null, false) ;
							
							return rs;
						}
					};

					return jdbcTransaction.doInTransaction();
				}
				else {
					throw new RuntimeException("this database does not supports batch updates.") ;
				}
			} else {
				return 0;
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}

	/**
	 * 释放数据库资源。
	 * 
	 * @param rs
	 * @param stmt
	 * @param conn
	 * @param isCloseConnection
	 *            是否关闭数据库连接。
	 * @throws SQLException
	 */
	public static void release(ResultSet rs, Statement stmt, Connection conn,
			boolean isCloseConnection) throws SQLException {
		if (rs != null) {
			rs.close();
			rs = null;
		}
		if (stmt != null) {
			stmt.close();
			stmt = null;
		}
		if (conn != null) {
			if (!conn.isClosed() && !conn.getAutoCommit()) {
				conn.rollback();
			}
			if (isCloseConnection) {
				conn.close();
				conn = null;
			}
		}
	}
	
	/**
	 * 
	 * @param connection
	 * @param autoCommit
	 * @throws SQLException
	 */
	public static void setAutoCommit(Connection connection, boolean autoCommit) throws SQLException {
		connection.setAutoCommit(autoCommit);
	}
	
	/**
	 * 是否支持ResultSet.TYPE_SCROLL_INSENSITIVE
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) ;
	}
	
	/**
	 * 是否支持ResultSet.CONCUR_READ_ONLY
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY) ;
	}
	
	/**
	 * 是否支持ResultSet.CONCUR_UPDATABLE
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_UPDATABLE(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE) ;
	}
	
	/**
	 * 是否支持 ANSI92 SQL
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsANSI92FullSQL(Connection connection) throws SQLException {
		return connection.getMetaData().supportsANSI92FullSQL() ;
	}
	
	/**
	 * 是否支持SelectForUpdate
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsSelectForUpdate(Connection connection) throws SQLException {
		return connection.getMetaData().supportsSelectForUpdate() ;
	}
	
	/**
	 * 是否支持批量更新。
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsBatchUpdates(Connection connection) throws SQLException {
		return connection.getMetaData().supportsBatchUpdates() ;
	}
	
	/**
	 * 是否支持事务保存点
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsSavepoints(Connection connection) throws SQLException {
		return connection.getMetaData().supportsSavepoints() ;
	}
	
	/**
	 * 设置事务保存点
	 * @param connection
	 * @param name
	 * @return
	 * @throws SQLException
	 */
	public static Savepoint setSavePoint(Connection connection, String name) throws SQLException {
		if (isSupportsSavepoints(connection)) {
			return connection.setSavepoint(name);
		} else {
			throw new RuntimeException("this database does not supports savepoints.") ;
		}
	}
	
	/**
	 * 回滚到事务点
	 * @param connection
	 * @param savepoint
	 * @throws SQLException
	 */
	public static void rollback(Connection connection, Savepoint savepoint) throws SQLException {
		if (savepoint == null) {
			connection.rollback();
		} else {
			if(isSupportsSavepoints(connection))
				connection.rollback(savepoint);
			else
				connection.rollback();
		} 
	}

	/**
	 * 回滚到事务点
	 * @param connection
	 * @throws SQLException
	 */
	public static void rollback(Connection connection) throws SQLException {
		connection.rollback();
	}
	
	/**
	 * 提交事务
	 * @param connection
	 * @param savepoint
	 */
	public static void commit(Connection connection, Savepoint savepoint) throws SQLException {
		if(savepoint == null) {
			if (!connection.getAutoCommit()) {
				connection.commit();
			}
		}
		else {
			if(isSupportsSavepoints(connection)) {
				if (!connection.getAutoCommit()) {
					connection.releaseSavepoint(savepoint);
				}
			}
			else {
				if (!connection.getAutoCommit()) {
					connection.commit();
				}
			}
		}
	}
	
	/**
	 * 提交事务
	 * @param connection
	 */
	public static void commit(Connection connection) throws SQLException {
		if (!connection.getAutoCommit()) {
  	        connection.commit();
  	     }
	}

	/**
	 * Classpath下加载属性文件资源。
	 * 
	 * @param filePath
	 *            文件路径(Classpath路径)
	 * @return
	 * @throws IOException
	 */
	public static Properties loadPropsClassLoader(String filePath)
			throws IOException {
		Properties props = new Properties();
		InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream(
				filePath);
		props.load(in);
		in.close();
		return props;
	}

	/**
	 * Classpath下加载属性文件资源。
	 * 
	 * @param filePath
	 *            文件路径(文件系统路径)
	 * @return
	 * @throws IOException
	 */
	public static Properties loadPropsSystem(String filePath)
			throws IOException {
		Properties props = new Properties();
		InputStream in = new FileInputStream(new File(filePath));
		props.load(in);
		in.close();
		return props;
	}

	/**
	 * 获取数据库连接数据源。
	 * 
	 * @param jndiName
	 *            jndi名称
	 * @return
	 * @throws NamingException
	 */
	public static DataSource getDataSource(String jndiName)
			throws NamingException {
		Context ctx = new InitialContext();
		DataSource ds = (DataSource) ctx.lookup(jndiName);
		return ds;
	}

	/**
	 * 测试数据库连接是否有效。
	 * 
	 * @param driver
	 * @param user
	 * @param password
	 * @param url
	 * @return
	 */
	public static boolean testConnection(String driver, String user,
			String password, String url) {
		try {
			Class.forName(driver).newInstance();
			Connection connection = DriverManager.getConnection(url, user,
					password);

			DatabaseMetaData metaData = connection.getMetaData();

			if (user.equals(metaData.getUserName())) {
				return true;
			}

		} catch (InstantiationException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (IllegalAccessException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (ClassNotFoundException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (SQLException e) {
			logger.error("测试数据库连接异常", e) ;
		}
		return false;
	}
}


/**
 * jdbc
 */
package org.liufei.sql;

/**
 * get a database datasource({@link org.liufei.sql.DataSourceConnection})
 * connection({@link java.sql.Connection}) from jdbc
 * 
 * @author liufei
 * 
 */
public interface JdbcDataSource extends DataSourceConnection {

	/**
	 * 返回数据库驱动字符串。
	 * 
	 * @return
	 */
	String getDriver();

	/**
	 * 返回连接数据库的URL
	 * 
	 * @return
	 */
	String getURL();

	/**
	 * 返回数据库的用户名
	 * 
	 * @return
	 */
	String getUsername();

	/**
	 * 返回与已绑定用户名对应数据库密码
	 * 
	 * @return
	 */
	String getPassword();
}
/**
 * jndi
 */
package org.liufei.sql;

import javax.naming.NamingException;
import javax.sql.DataSource;

/**
 * get a database datasource({@link org.liufei.sql.DataSourceConnection})
 * connection({@link java.sql.Connection}) from jndi
 * 
 * @author liufei
 * 
 */
public interface JndiDataSource extends DataSourceConnection {

	/**
	 * 返回一个可用的的jndi名称。 如:java:comp/env/jdbc/mysql <br/>
	 * 
	 * &lt?xml version='1.0' encoding='utf-8'?&gt<br/> &ltContext&gt<br/>
	 * &lt!-- Default set of monitored resources --&gt<br/>
	 * &ltWatchedResource&gtWEB-INF/web.xml&lt/WatchedResource&gt<br/>
	 * &ltResource driverClass="com.mysql.jdbc.Driver"<br/>
	 * jdbcUrl="jdbc:mysql://localhost:3306/hw_man_13?characterEncoding=GBK&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;zeroDateTimeBehavior=convertToNull"<br/>
	 * user="root"<br/> password="root"<br/> name="jdbc/mysql"<br/>
	 * factory="org.apache.naming.factory.BeanFactory"<br/>
	 * type="com.mchange.v2.c3p0.ComboPooledDataSource"<br/>
	 * initialPoolSize="2"<br/> maxPoolSize="2"<br/> maxIdleTime="25000"<br/>
	 * idleConnectionTestPeriod ="18000"<br/> auth="Container"<br/>
	 * acquireIncrement="3"<br/> checkoutTimeout="200000"<br/> /&gt<br/>
	 * &lt/Context&gt<br/>
	 * 
	 * @return
	 */
	String getJndiName();

	/**
	 * 获取已绑定jndi名称(通过getJndiName()方法绑定)的数据源
	 * 
	 * @return
	 * @throws NamingException
	 */
	DataSource getDataSource() throws NamingException;

	/**
	 * 获取制定jndi名称的数据源
	 * 
	 * @param jndiname
	 * @return
	 * @throws NamingException
	 */
	DataSource getDataSource(String jndiname) throws NamingException;
}
package org.liufei.sql;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * get a database datasource({@link org.liufei.sql.DataSourceConnection}) connection({@link java.sql.Connection})
 * 
 * @author liufei
 * 
 */
public interface DataSourceConnection {

	/**
	 * 返回一个活跃的可用连接
	 * 
	 * @link java.sql.Connection
	 * @return 返回一个活跃的可用连接
	 * @throws SQLException
	 */
	Connection getConnection() throws SQLException;

	/**
	 * 返回一个活跃的可用连接
	 * @link java.sql.Connection
	 * @param username 需要进一步验证用户名
	 * @param password 需要进一步验证密码
	 * @return 返回一个活跃的可用连接
	 * @throws SQLException
	 */
	Connection getConnection(String username, String password)
			throws SQLException;

}
package org.liufei.sql.impl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.liufei.sql.JdbcDataSource;
import org.liufei.sql.util.ClasspathConfig;

/**
 * 默认的jdbc实现。
 * 
 * @author 刘飞
 * 
 */
public class Jdbc implements JdbcDataSource {
	private static final Logger logger = Logger.getLogger(Jdbc.class.getName());

	@Override
	public String getDriver() {
		return ClasspathConfig.getDriver();
	}

	@Override
	public String getPassword() {
		return ClasspathConfig.getPassword();
	}

	@Override
	public String getURL() {
		return ClasspathConfig.getUrl();
	}

	@Override
	public String getUsername() {
		return ClasspathConfig.getUsername();
	}

	@Override
	public Connection getConnection() throws SQLException {
		try {
			return this.getConnection(this.getDriver(), this.getURL(), this
					.getUsername(), this.getPassword());
		} catch (InstantiationException e) {
			logger
					.log(Level.WARNING, "加载数据库驱动时异常:\n"
							+ e.getLocalizedMessage());
			return null;
		} catch (IllegalAccessException e) {
			logger
					.log(Level.WARNING, "加载数据库驱动时异常:\n"
							+ e.getLocalizedMessage());
			return null;
		} catch (ClassNotFoundException e) {
			logger
					.log(Level.WARNING, "加载数据库驱动时异常:\n"
							+ e.getLocalizedMessage());
			return null;
		}
	}

	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		if (!(username.equals(getUsername()) && password.equals(getPassword()))) {
			logger.log(Level.WARNING, "非法的用户名和密码.\n");
			return null;
		} else {
			try {
				return this.getConnection(this.getDriver(), this.getURL(), this
						.getUsername(), this.getPassword());
			} catch (InstantiationException e) {
				logger.log(Level.WARNING, "加载数据库驱动时异常:\n"
						+ e.getLocalizedMessage());
				return null;
			} catch (IllegalAccessException e) {
				logger.log(Level.WARNING, "加载数据库驱动时异常:\n"
						+ e.getLocalizedMessage());
				return null;
			} catch (ClassNotFoundException e) {
				logger.log(Level.WARNING, "加载数据库驱动时异常:\n"
						+ e.getLocalizedMessage());
				return null;
			}
		}
	}

	/**
	 * 
	 * @param driver
	 * @param url
	 * @param username
	 * @param password
	 * @return
	 * @throws SQLException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	private Connection getConnection(String driver, String url,
			String username, String password) throws SQLException,
			InstantiationException, IllegalAccessException,
			ClassNotFoundException {
		Class.forName(driver).newInstance();
		return DriverManager.getConnection(url, username, password);
	}
}
package org.liufei.sql.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.liufei.sql.JndiDataSource;
import org.liufei.sql.util.ClasspathConfig;

/**
 * 默认的jndi实现。
 * @author 刘飞
 *
 */
public class Jndi implements JndiDataSource {
	private static final Logger logger = Logger.getLogger(Jndi.class.getName());

	@Override
	public DataSource getDataSource() throws NamingException {
		return this.getDataSource(this.getJndiName());
	}

	@Override
	public DataSource getDataSource(String jndiname) throws NamingException {
		Context ctx = new InitialContext();
		DataSource ds = (DataSource)ctx.lookup(jndiname);
		return ds;
	}

	@Override
	public String getJndiName() {
		return ClasspathConfig.getJndiname();
	}

	@Override
	public Connection getConnection() throws SQLException {
		try {
			return this.getDataSource().getConnection();
		} catch (NamingException e) {
			logger.log(Level.WARNING, "JNDI名称查找失败 : " + e.getLocalizedMessage()) ;
			return null ;
		}
	}

	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		try {
			return this.getDataSource().getConnection(username, password);
		} catch (NamingException e) {
			logger.log(Level.WARNING, "JNDI名称查找失败 : " + e.getLocalizedMessage()) ;
			return null ;
		}
	}

}
package org.liufei.sql.callback;

import java.sql.SQLException;
import java.sql.Wrapper;

/**
 * 在SQL api包中的所有接口中回调。
 * 
 * @author 刘飞
 * 
 * @param <T>
 *            返回类型
 * @param <K>
 *            sql api
 */
public interface Callback<T, K extends Wrapper> {

	/**
	 * 在SQL api包中的所有接口中回调。
	 * 
	 * @param k
	 *            SQL api包中的所有接口
	 * @return
	 * @throws SQLException
	 */
	T doInSql(K k) throws SQLException;

}
package org.liufei.sql.callback;


import java.sql.SQLException;
import java.sql.Wrapper;

/**
*
* @author 刘飞
*
* @param <T>
*            返回类型。
* @param <K>
*            sql api的回调。
*/
public interface SqlCallback<T, K extends Wrapper> {

/**
* 调用一个回调对象,完成真正的回调转换。
*
* @param sql
* @param callback
* @return
* @throws SQLException
*/
T doInSQLCallback(String sql, Callback<T, K> callback) throws SQLException;
}
package org.liufei.sql.callback;

import java.sql.Connection;

/**
 * 在Connection中回调。
 * @author 刘飞
 *
 * @param <T>
 */
public interface ConnectionCallback<T> extends Callback<T, Connection>{
	
}
package org.liufei.sql.callback;

import javax.sql.DataSource;

/**
 * DataSource中回调。
 * 
 * @author 刘飞
 * 
 * @param <T>
 */
public interface DataSourceCallback<T> extends Callback<T, DataSource> {

}
package org.liufei.sql.callback;

import java.sql.PreparedStatement;

/**
 * 在PreparedStatement中回调。
 * @author 刘飞
 *
 * @param <T>
 */
public interface PreparedStatementCallback<T> extends Callback<T, PreparedStatement>{

}
package org.liufei.sql.callback;

import java.sql.ResultSet;

/**
 * 在ResultSet中回调。
 * @author 刘飞
 *
 * @param <T>
 */
public interface ResultSetCallback<T> extends Callback<T, ResultSet> {

}
package org.liufei.sql.callback;

import java.sql.Statement;

/**
 * 在Statement回调。
 * @author 刘飞
 *
 * @param <T>
 */
public interface StatementCallback<T> extends Callback<T, Statement> {

}
package org.liufei.sql.callback.help;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Wrapper;

import javax.sql.DataSource;

import org.liufei.sql.callback.CallableStatementCallback;
import org.liufei.sql.callback.Callback;
import org.liufei.sql.callback.ConnectionCallback;
import org.liufei.sql.callback.DataSourceCallback;
import org.liufei.sql.callback.DatabaseMetaDataCallback;
import org.liufei.sql.callback.ParameterMetaDataCallback;
import org.liufei.sql.callback.PreparedStatementCallback;
import org.liufei.sql.callback.ResultSetCallback;
import org.liufei.sql.callback.ResultSetMetaDataCallback;
import org.liufei.sql.callback.SqlCallback;
import org.liufei.sql.callback.StatementCallback;

/**
 * SQL回调的抽象实现。
 * 
 * @author 刘飞
 * 
 * @param <T>
 *            返回类型
 * @param <K>
 *            sql api的回调。
 */
public abstract class CommonSqlCallback<T> implements
		SqlCallback<T, Wrapper> {

	protected Connection connection = null ;
	
	protected DataSource dataSource = null ;

	private static final int DEFAULT_TIMEOUT = 2 ;//2秒中的数据库连接测试。

	public CommonSqlCallback(Connection connection) throws SQLException {
		super();
		this.connection = connection;
		if( this.connection.isClosed() || this.connection.isValid(DEFAULT_TIMEOUT) ) {
			throw new SQLException( this.getClass() + " construct sql connection exception : Illegal unavailable database connection ." ) ;
		}
	}

	public CommonSqlCallback(DataSource dataSource) throws SQLException {
		this(dataSource.getConnection()) ;
		this.dataSource = dataSource;
	}

	@Override
	public T doInSQLCallback(String sql, Callback<T, Wrapper> callback)
			throws SQLException {
		if(this.connection != null) {
			if(callback instanceof ConnectionCallback) {
				return callback.doInSql(this.connection) ;
			}
			else if(callback instanceof PreparedStatementCallback) {
				PreparedStatement pstmt = this.connection.prepareStatement(sql) ;
				return callback.doInSql(pstmt) ;
			}
			else if(callback instanceof StatementCallback) {
				Statement stmt = this.connection.createStatement() ;
				return callback.doInSql(stmt) ;
			}
			else if(callback instanceof CallableStatementCallback) {
				CallableStatement cstmt = this.connection.prepareCall(sql) ;
				return callback.doInSql(cstmt) ;
			}
			else if(callback instanceof DatabaseMetaDataCallback) {
				DatabaseMetaData dbmd = this.connection.getMetaData() ;
				return callback.doInSql(dbmd) ;
			}
			else if(callback instanceof ResultSetCallback) {
				ResultSet rs = this.connection.prepareCall(sql).executeQuery() ;
				return callback.doInSql(rs) ;
			}
			else if(callback instanceof ResultSetMetaDataCallback) {
				ResultSetMetaData rsmd = this.connection.prepareStatement(sql).getMetaData() ;
				return callback.doInSql(rsmd) ;
			}
			else if(callback instanceof ParameterMetaDataCallback) {
				ParameterMetaData pmd = this.connection.prepareCall(sql).getParameterMetaData() ;
				return callback.doInSql(pmd) ;
			}
			else {
				// no result
			}
		}
		
		if(this.dataSource !=  null) {
			if(callback instanceof DataSourceCallback) {
				return callback.doInSql(this.dataSource) ;
			}
		}
		return null ;
	}
}
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=GBK&autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull
jdbc.username=root
jdbc.password=root
jdbc.jndiname=java:comp/env/jdbc/mysql