關於連線bean中可能發生多執行緒的問題請教,歡迎大家一起討論

摩卡碳燒發表於2004-08-25

收費資訊綜合查詢,即在市局可以查到各分局的收費資訊。

單位名稱    資料庫     DataSource      所在應用伺服器
某市局      db_0       jdbc/test       192.168.1.0
A分局       db_1       jdbc/test1      192.168.1.1
B分局       db_2       jdbc/test2      192.168.1.2 
C分局       db_3       jdbc/test3      192.168.1.3
D分局       db_4       jdbc/test4      192.168.1.4
E分局       db_5       jdbc/test5      192.168.1.5

/////////////////////////////////////////////////////////////////////////
192.168.1.0上的resin.conf內容如下:

<resource-ref>
  <res-ref-name>jdbc/test</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.0:5000/db_0"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test1</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.1:5000/db_1"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test2</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.2:5000/db_2"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test3</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.3:5000/db_3"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test4</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.4:5000/db_4"/>
  ....................
</resource-ref>

<resource-ref>
  <res-ref-name>jdbc/test5</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param url="jdbc:sybase:Tds:192.168.1.5:5000/db_5"/>
  ....................
</resource-ref>


////////////////////////////////////////////////////////////////////////

package com.kysoft.jndi;
/**
 * Title:        DbFactory
 * Description:  資料庫連線的實現類
 * Copyright:    Copyright (c) 2004
 */

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;


public class DbFactory {
    
    private static DataSource ds = null; //****
    private static Object initDSLock = new Object();
    
    public DbFactory() 
    {}

    /**
     * 在後臺管理中需要獲得資料庫了連線
     * @return Connection
     */
    private static DataSource lookupDS(String dsName) 
    {                 
        if (ds == null) 
        {
            synchronized (initDSLock)
            {
                if (ds == null) 
                {
                    try 
                    {
                      Context ctx =(Context)new InitialContext().lookup("java:comp/env");
                      ds = (DataSource)ctx.lookup(dsName);
                    } 
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
        return ds;
    }
    

    //protected
    public static Connection getConnection(String dsName) 
    {
        Connection conn = null;
        try {
                conn = lookupDS(dsName).getConnection(); 
        }       
        catch (Exception e) {
            e.printStackTrace();
        }
        return conn;    
     }


    public static void closeDB(
        ResultSet rs,
        PreparedStatement pstmt,
        Statement stmt,
        Connection con) {
        try {
            if (rs != null)
                rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (pstmt != null)
                pstmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (stmt != null)
                stmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (con != null)
                con.close();                
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    public static void cleanDS()
    {
           if(ds!=null){
              ds=null;
           }
    }
     
}


//////////////////////////////////////////////////////////////////////////////
query.jsp
<%

  com.kysoft.jndi.DbFactory DbFactory=null; 
  Connection conn=null;
  Statement stmt=null;
  ResultSet rs=null;
  String    dbparm=null;
//查詢每一個分局的收費情況


//模擬各個分局的DataSource
String dw_array[]=new String[]{"jdbc/test1","jdbc/test2","jdbc/test3","jdbc/test4","jdbc/test5"};

//迴圈每一個分局
for(int i=0;i<dw_array.length;i++)
{
    dbparm=dw_array[i]; //取得DS,例如:jdbc/test1
    DbFactory.cleanDS(); //清除DS
    conn=DbFactory.getConnection(dbparm);//得到當前分局的資料庫連線
    /*
      因為jsp是多執行緒,連線bean中private static DataSource ds,所以,很有可能當第二個統計執行緒發生時,他的ds被其它執行緒篡改,以致連線到錯誤的資料庫中。
    */
    stmt=conn.createStatement();
    rs=stmt.executeQuery("select sum(money) from table");
    out.println("第"+i+"分局彙總金額="+rs.getInt(1));
    .........
    .........

    DbFactory.closeDB(rs,null,stmt,conn);//關閉資料庫連線
}

%>


請問,bean中應該怎麼處理,才會避免這種情況發生?而且使效率還最優。
<p class="indent">

相關文章