package com.ketayao.fensy.db; import com.ketayao.fensy.Constants; import com.ketayao.fensy.exception.DBException; import org.apache.commons.beanutils.BeanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sql.DataSource; 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; /** * 数据库管理 */ public class DBManager { private final static Logger log = LoggerFactory .getLogger(DBManager.class); private final static ThreadLocal<Connection> conns = new ThreadLocal<Connection>(); private static DataSource dataSource; private static boolean showSql = false; public static String prefixTableName = ""; static { initDataSource(null); } public static DataSource getDataSource() { return dataSource; } /** * 初始化连接池 * @param props * @param show_sql */ private final static void initDataSource(Properties dbProperties) { try { if (dbProperties == null) { dbProperties = new Properties(); dbProperties.load(DBManager.class .getResourceAsStream("/" + Constants.FENSY_CONFIG_FILE)); } Properties props = new Properties(); for (Object key : dbProperties.keySet()) { String skey = (String) key; if (skey.startsWith("jdbc.")) { String name = skey.substring(5); props.put(name, dbProperties.getProperty(skey)); if ("showSql".equalsIgnoreCase(name)) { showSql = "true".equalsIgnoreCase(dbProperties.getProperty(skey)); } else if ("prefixTableName".equalsIgnoreCase(name)) { prefixTableName = dbProperties.getProperty(skey); } } } dataSource = (DataSource) Class.forName(props.getProperty("dataSource")).newInstance(); if (dataSource.getClass().getName().indexOf("c3p0") > 0) { // Disable JMX in C3P0 System.setProperty("com.mchange.v2.c3p0.management.ManagementCoordinator", "com.mchange.v2.c3p0.management.NullManagementCoordinator"); } log.info("Using DataSource : " + dataSource.getClass().getName()); BeanUtils.populate(dataSource, props);// 将props的值注入dataSource属性。 Connection conn = getConnection(); DatabaseMetaData mdm = conn.getMetaData(); log.info("Connected to " + mdm.getDatabaseProductName() + " " + mdm.getDatabaseProductVersion()); closeConnection(); } catch (Exception e) { throw new DBException(e); } } /** * 断开连接池 */ public final static void closeDataSource() { try { dataSource.getClass().getMethod("close").invoke(dataSource); } catch (NoSuchMethodException e) { } catch (Exception e) { log.error("Unabled to destroy DataSource!!! ", e); } } /** * 获取连接 * @return * @throws SQLException */ public final static Connection getConnection() throws SQLException { Connection conn = conns.get(); if (conn == null || conn.isClosed()) { conn = dataSource.getConnection(); conns.set(conn); } return (showSql && !Proxy.isProxyClass(conn.getClass())) ? new DebugConnection(conn) .getConnection() : conn; } /** * 关闭连接 */ public final static void closeConnection() { Connection conn = conns.get(); try { if (conn != null && !conn.isClosed()) { conn.setAutoCommit(true); conn.close(); } } catch (SQLException e) { log.error("Unabled to close connection!!! ", e); } conns.remove(); } /** * 用于跟踪执行的SQL语句 */ static class DebugConnection implements InvocationHandler { private final static Logger log = LoggerFactory.getLogger(DebugConnection.class); private Connection conn = null; public DebugConnection(Connection conn) { this.conn = conn; } /** * Returns the conn. * @return Connection */ public Connection getConnection() { return (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn .getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { try { String method = m.getName(); if ("prepareStatement".equals(method) || "createStatement".equals(method)) log.info("[SQL] >>> " + args[0]); return m.invoke(conn, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } } }