/** * Copyright (c) 2011-2014, 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.HashSet; import java.util.Map; import java.util.Set; import javax.sql.DataSource; import com.jfinal.kit.StringKit; 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; public class Config { String name; private final ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); DataSource dataSource; int transactionLevel = Connection.TRANSACTION_READ_COMMITTED; ICache cache = new EhCache(); boolean showSql = false; boolean devMode = false; Dialect dialect = new MysqlDialect(); IContainerFactory containerFactory = new IContainerFactory(){ public Map<String, Object> getAttrsMap() {return new HashMap<String, Object>();} public Map<String, Object> getColumnsMap() {return new HashMap<String, Object>();} public Set<String> getModifyFlagSet() {return new HashSet<String>();} }; /** * For DbKit.brokenConfig = new Config(); */ Config() { } /** * Constructor with DataSource * @param dataSource the dataSource, can not be null */ public Config(String name, DataSource dataSource) { if (StringKit.isBlank(name)) throw new IllegalArgumentException("Config name can not be blank"); if (dataSource == null) throw new IllegalArgumentException("DataSource can not be null"); this.name = name.trim(); this.dataSource = dataSource; } /** * Constructor with DataSource and Dialect * @param dataSource the dataSource, can not be null * @param dialect the dialect, can not be null */ public Config(String name, DataSource dataSource, Dialect dialect) { if (StringKit.isBlank(name)) throw new IllegalArgumentException("Config name can not be blank"); if (dataSource == null) throw new IllegalArgumentException("DataSource can not be null"); if (dialect == null) throw new IllegalArgumentException("Dialect can not be null"); this.name = name.trim(); this.dataSource = dataSource; this.dialect = dialect; } /** * Constructor with full parameters * @param dataSource the dataSource, can not be null * @param dialect the dialect, set null with default value: new MysqlDialect() * @param showSql the showSql,set null with default value: false * @param devMode the devMode, set null with default value: false * @param transactionLevel the transaction level, set null with default value: Connection.TRANSACTION_READ_COMMITTED * @param containerFactory the containerFactory, set null with default value: new IContainerFactory(){......} * @param cache the cache, set null with default value: new EhCache() */ public Config(String name, DataSource dataSource, Dialect dialect, Boolean showSql, Boolean devMode, Integer transactionLevel, IContainerFactory containerFactory, ICache cache) { if (StringKit.isBlank(name)) throw new IllegalArgumentException("Config name can not be blank"); if (dataSource == null) throw new IllegalArgumentException("DataSource can not be null"); this.name = name.trim(); this.dataSource = dataSource; if (dialect != null) this.dialect = dialect; if (showSql != null) this.showSql = showSql; if (devMode != null) this.devMode = devMode; if (transactionLevel != null) this.transactionLevel = transactionLevel; if (containerFactory != null) this.containerFactory = containerFactory; if (cache != null) this.cache = cache; } public String getName() { return name; } public Dialect getDialect() { return dialect; } public ICache getCache() { return cache; } public int getTransactionLevel() { return transactionLevel; } public DataSource getDataSource() { return dataSource; } public IContainerFactory getContainerFactory() { return containerFactory; } public boolean isShowSql() { return showSql; } public boolean isDevMode() { return devMode; } // -------- /** * Support transaction with Transaction interceptor */ public final void setThreadLocalConnection(Connection connection) { threadLocal.set(connection); } public final void removeThreadLocalConnection() { threadLocal.remove(); } /** * Get Connection. Support transaction if Connection in ThreadLocal */ public final Connection getConnection() throws SQLException { Connection conn = threadLocal.get(); if (conn != null) return conn; return showSql ? new SqlReporter(dataSource.getConnection()).getConnection() : dataSource.getConnection(); } /** * Helps to implement nested transaction. * Tx.intercept(...) and Db.tx(...) need this method to detected if it in nested transaction. */ public final Connection getThreadLocalConnection() { return threadLocal.get(); } /** * Close ResultSet、Statement、Connection * ThreadLocal support declare transaction. */ public 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 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 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);} } }