聊聊TheadLocal

  TheadLocal 中文叫做线程局部变量,它为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

  其实主要想讲的是它的数据库连接方面的作用,就是保证一个线程一个事务一个session。由于请求中的一个事务涉及多个 DAO 操作,而这些 DAO 中的 Connection 
不能从连接池中获得,如果是从连接池获得的话,两个 DAO 就用到了两个Connection,这样的话是没有办法完成一个事务的。DAO 中的 Connection 如果是从 ThreadLocal 中获得 Connection 的话那么这些 DAO 就会被纳入到同一个 Connection 之下。当然了,这样的话,DAO 中就不能把 Connection 给关了,关掉的话,下一个使用者就不能用了。

public class DataSourceFactory{

    private static DataSource ds = null;



    private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();



    /**

     * 使用JNDI方式获得数据库源

     * 需要在tomcat/conf/context.xml中配置数据源,如下:

     * <Resource name="jdbc/forceviewDB" type="javax.sql.DataSource" username="forceview" password="forceview" 

        url="jdbc:postgresql://localhost/forceview?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf-8" 

        driverClassName="org.postgresql.Driver" maxIdle="3" maxWait="-1" maxActive="50" 

        validationQuery="select 1" 

        testOnBorrow="true" 

        testOnReturn="true" 

        testWhileIdle="true" 

        removeAbandoned="true" 

        removeAbandonedTimeout="180" 

        logAbandoned="true" 

        timeBetweenEvictionRunsMillis="180000" 

        minEvictableIdleTimeMillis = "180000"

        />

     *注意相关jar包的引入

     * @param jndi

     */

    public static void init(String jndi) {

        if(jndi==null||"".equals(jndi)){

            jndi="java:/comp/env/jdbc/forceviewDB";

        }

        try {

            Context initContext = new InitialContext();

            ds = (DataSource) initContext.lookup(jndi);

        } catch (Exception e) {

            DhccLogger.error("", e);



        }

    }

    /**

     * 使用从spring的ApplicationContext对象中得到的数据源给ds赋值

     * @param ctx

     */

    public static void init(ApplicationContext ctx) {

        try {

            ds = (DataSource) ctx.getBean("dataSource");

        } catch (RuntimeException e) {

            DhccLogger.error("", e);

        }

    }

    /**

     * 使用数据库源给ds赋值

     * @param dataSource

     */

    public static void init(DataSource dataSource) {

        ds=dataSource;

    }



    /**

     * 获取数据库连接

     * 如果threadLocal中没有连接,或者其中的连接已经关闭,

     * 则从数据库连接池中获得,并保存于threadLocal中

     * @return

     */

    public static Connection getConnection() {

        Connection conn = threadLocal.get();



        try {

            if (conn == null || conn.isClosed()) {

                conn = ds.getConnection();

                threadLocal.set(conn);

            }

        } catch (Exception e) {

            DhccLogger.error("", e);

        }

        return conn;

    }



    /**

     * 关闭数据库连接

     * 此方法不进行任何操作,在操作数据库时,习惯最后关闭数据库连接,

     * 应用此类取得的数据库连接最好不要立即关闭,为了习惯,可以使用此方法来代替connection.close()方法

     */

    public static void closeConnection() {

    }



    /**

     * 关闭数据库连接,把数据库连接归还连接池,

     * 此连接对应于连接池中的连接并没有真正关闭,仍由连接池维护

     */

    public static void close() {

        Connection conn = (Connection) threadLocal.get();

        threadLocal.set(null);

        if (conn != null) {

            try {

                conn.close();

            } catch (SQLException e) {

                DhccLogger.error("", e);

            }

        }

    }

}

 

你可能感兴趣的:(local)