All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.tom.mvc.jdbc.DBPool Maven / Gradle / Ivy

There is a newer version: 1.0.3
Show newest version
package cn.tom.mvc.jdbc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.tom.kit.Encrypt;
import cn.tom.kit.clazz.ReflectUtil;
import cn.tom.kit.io.FileUtil;

public final class DBPool {
	private DataSource dataSource;
	public String driverClass;
	private String username;
	private String password;
	private final static ThreadLocal conns = new ThreadLocal();
	private File dbFile;
	private int flag = 0;
	public static Logger logger = LoggerFactory.getLogger(DBPool.class);
	public static boolean show_sql = false;

	public DBPool() {
	}
	
	public DBPool(File dbFile) {
		this.dbFile = dbFile;
		init();
	}

	public String getPassword() {
		return password;
	}

	public String getUsername() {
		return username;
	}
	
	public void init(Properties prop) {
		this.flag += 1;
		logger.info("init connection " + this.flag + " times");
		try {
			this.driverClass = prop.getProperty("driverClassName");
			show_sql = Boolean.parseBoolean(prop.getProperty("show_sql"));
			String encrypt = prop.getProperty("encrypt");
			prop.remove("show_sql");
			prop.remove("encrypt");

			this.username = prop.getProperty("username");
			this.password = prop.getProperty("password");
			if (encrypt != null && !encrypt.isEmpty()) { // 如果是加密状态需要解密
				prop.setProperty("password", Encrypt.decryptString(2, password));
			}
			/* 使用class加载器 代替forName(forName会初始化一次) */
			this.dataSource = (DataSource) Thread.currentThread().getContextClassLoader().loadClass(prop.getProperty("dataSource")).newInstance();
			// this.dataSource = (DataSource)
			// Class.forName(prop.getProperty("dataSource")).newInstance();
			prop.remove("dataSource");

			/* dataSource set方法注入 */
			ReflectUtil.populate(dataSource, prop);
			Connection conn = getConnection();
			DatabaseMetaData mdm = conn.getMetaData();

			logger.info("connect database success: " + mdm.getDatabaseProductName() + mdm.getDatabaseProductVersion());
			closeConnection(conn);
		} catch (Exception e) {
			logger.error("init connection failed in " + this.flag + " times", e);
		}
	}

	public void init() {
		Properties prop = new Properties();
		InputStream in = null;
		try{
			in =  new FileInputStream(dbFile);
			prop.load(in);
		}catch(IOException e){
			logger.info("read dbconfig error", e);
		}finally{
			FileUtil.close(in, null);
		}
		init(prop);

	}

	/**
	 * 断开连接池
	 */
	public final void closeDataSource() {
		try {
			if(dataSource == null) return;
			dataSource.getClass().getMethod("close").invoke(dataSource);
			dataSource = null;
		} catch (Exception e) {
		}
	}
	
	private final Connection proxyConn(Connection conn) {
		return (show_sql && !Proxy.isProxyClass(conn.getClass())) ? new _DebugConnection().bindConnection(conn) : conn;
	}
	
	/**
	 * 默认初始化两次
	 */
	public Connection getConnection() throws SQLException {
		try {
			/*return proxyConn(dataSource.getConnection());*/
			return dataSource.getConnection();
		} catch (SQLException e) {
			logger.error("init connection failed, init again..." + e.toString());
			init();
			try {
				return dataSource.getConnection();
			} catch (SQLException ee) {
				logger.info("init connection faild, check DBconfig!" + ee.toString());
				throw ee;
			}
		}
	}

	/**
	 * servlet 都会使用线程池, 线程池中线程重复利用 
	 * request对应的ThreadLocaL可能获取同一个Connetion,此时connection 可能已经被关闭
	 * 解决方案: 每次获取时都新建connetion, 关闭时从 ThreadLocal 中获取关闭,保证了connetion的有效性
	 * @return
	 */
	@Deprecated
	public final Connection getThreadConnection() {
		Connection conn = conns.get();
		try {
			if (conn == null || conn.isClosed()) {
				conn = getConnection();
			}
		} catch (SQLException e) {
		}
		conns.set(conn);
		return proxyConn(conn);
	}

	/**
	 * 关闭连接线程局部变量连接
	 */
	@Deprecated
	public final void closeThreadConnection() {
		Connection conn = conns.get();
		try {
			if (conn != null) {
				conn.close();
			}
		} catch (SQLException e) {
		}
		conns.remove();
	}

	/**
	 * 关闭连接
	 * 
	 * @param conn
	 */
	public final void closeConnection(Connection conn) {
		try {
			if (conn != null) {
				conn.close();
			}
		} catch (SQLException e) {
		}
	}

	/**
	 * 用于跟踪执行的SQL语句
	 * 由于无法 追踪 sql 执行参数 暂不使用
	 * @author Winter Lau
	 * @deprecated
	 */
	static class _DebugConnection implements InvocationHandler {
		private Connection conn = null;

		/**
		 * Returns the conn.
		 * 
		 * @return Connection
		 */
		public Connection bindConnection(Connection conn) {
			this.conn = conn;
			return (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), this);
		}

		@Override
		public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
			String methodName = m.getName();
			if ("prepareStatement".equals(methodName) ||  "prepareCall".equals(methodName)) {
				logger.info("[SQL]>> " + args[0]);
			}
			try {
				return m.invoke(conn, args);
			} catch (InvocationTargetException e) {
				throw e.getTargetException();
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy