最近公司使用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/>
*
* <?xml version='1.0' encoding='utf-8'?><br/> <Context><br/>
* <!-- Default set of monitored resources --><br/>
* <WatchedResource>WEB-INF/web.xml</WatchedResource><br/>
* <Resource driverClass="com.mysql.jdbc.Driver"<br/>
* jdbcUrl="jdbc:mysql://localhost:3306/hw_man_13?characterEncoding=GBK&autoReconnect=true&failOverReadOnly=false&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/> /><br/>
* </Context><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