/** * Copyright (c) 2011-2012, James Zhan 詹波 (jfinal@126.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jfinal.plugin.activerecord; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import com.jfinal.plugin.activerecord.cache.EhCache; import com.jfinal.plugin.activerecord.cache.ICache; import com.jfinal.plugin.activerecord.dialect.Dialect; import com.jfinal.plugin.activerecord.dialect.MysqlDialect; /** * DbKit */ public final class DbKit { private static DataSource dataSource; private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); static final Object[] NULL_PARA_ARRAY = new Object[0]; private static int transactionLevel = Connection.TRANSACTION_READ_COMMITTED; private static ICache cache = new EhCache(); private static boolean showSql = false; static boolean devMode = false; static Dialect dialect = new MysqlDialect(); static IMapFactory mapFactory = new IMapFactory(){ public Map<String, Object> getAttrsMap() {return new HashMap<String, Object>();} public Map<String, Object> getColumnsMap() {return new HashMap<String, Object>();} }; static void setMapFactory(IMapFactory mapFactory) { if (mapFactory != null) DbKit.mapFactory = mapFactory; } static void setDevMode(boolean devMode) { DbKit.devMode = devMode; } static void setShowSql(boolean showSql) { DbKit.showSql = showSql; } static void setDialect(Dialect dialect) { if (dialect != null) DbKit.dialect = dialect; } static void setCache(ICache cache) { DbKit.cache = cache; } public static Dialect getDialect() { return dialect; } public static ICache getCache() { return cache; } // Prevent new DbKit() private DbKit() { } /** * Inject DataSource */ public static final void setDataSource(DataSource dataSource) { DbKit.dataSource = dataSource; } static final void setTransactionLevel(int transactionLevel) { DbKit.transactionLevel = transactionLevel; } public static final int getTransactionLevel() { return transactionLevel; } /** * Get DataSrouce */ public static final DataSource getDataSource() { return dataSource; } /** * Support transaction with Transaction interceptor */ public static final void setThreadLocalConnection(Connection connection) { threadLocal.set(connection); } public static final void removeThreadLocalConnection() { threadLocal.remove(); // threadLocal.set(null); } /** * Get Connection. Support transaction if Connection in ThreadLocal */ public static final Connection getConnection() throws SQLException { Connection conn = threadLocal.get(); if (conn != null) return conn; return showSql ? new SqlReporter(dataSource.getConnection()).getConnection() : dataSource.getConnection(); } /* backup before refactory public static final Connection getConnection() throws SQLException { Connection conn = threadLocal.get(); if (showSql) return conn != null ? conn : new SqlReporter(dataSource.getConnection()).getConnection(); else return conn != null ? conn : dataSource.getConnection(); }*/ /** * Helps to prevent nested transaction. * Tx.intercept(...) and Db.tx(...) need this method to detected if it in nested transaction. */ public static final boolean isExistsThreadLocalConnection() { return threadLocal.get() != null; } /** * Close ResultSet、Statement、Connection * ThreadLocal support declare transaction. */ public static final void close(ResultSet rs, Statement st, Connection conn) { if (rs != null) {try {rs.close();} catch (SQLException e) {}} if (st != null) {try {st.close();} catch (SQLException e) {}} if (threadLocal.get() == null) { // in transaction if conn in threadlocal if (conn != null) {try {conn.close();} catch (SQLException e) {throw new ActiveRecordException(e);}} } } public static final void close(Statement st, Connection conn) { if (st != null) {try {st.close();} catch (SQLException e) {}} if (threadLocal.get() == null) { // in transaction if conn in threadlocal if (conn != null) {try {conn.close();} catch (SQLException e) {throw new ActiveRecordException(e);}} } } public static final void close(Connection conn) { if (threadLocal.get() == null) // in transaction if conn in threadlocal if (conn != null) try {conn.close();} catch (SQLException e) {throw new ActiveRecordException(e);} } static final void closeIgnoreThreadLocal(Connection conn) { if (conn != null) try {conn.close();} catch (SQLException e) {throw new ActiveRecordException(e);} } static final void closeQuietly(ResultSet rs, Statement st) { if (rs != null) {try {rs.close();} catch (SQLException e) {}} if (st != null) {try {st.close();} catch (SQLException e) {}} } static final void closeQuietly(Statement st) { if (st != null) {try {st.close();} catch (SQLException e) {}} } public static String replaceFormatSqlOrderBy(String sql) { sql = sql.replaceAll("(\\s)+", " "); int index = sql.toLowerCase().lastIndexOf("order by"); if (index > sql.toLowerCase().lastIndexOf(")")) { String sql1 = sql.substring(0, index); String sql2 = sql.substring(index); sql2 = sql2.replaceAll("[oO][rR][dD][eE][rR] [bB][yY] [\u4e00-\u9fa5a-zA-Z0-9_.]+((\\s)+(([dD][eE][sS][cC])|([aA][sS][cC])))?(( )*,( )*[\u4e00-\u9fa5a-zA-Z0-9_.]+(( )+(([dD][eE][sS][cC])|([aA][sS][cC])))?)*", ""); return sql1 + sql2; } return sql; } }