2011-01-31 98 views
7

我有一個應用程序將與MySQL建立數據庫連接並執行查詢。有時DriverManager.getConnection()方法調用需要2秒,有時需要30秒。有沒有什麼辦法可以控制這種方法在2秒後超時?如何強制DriverManager.getConnection()方法調用超時?

DriverManager.setLoginTimeout()似乎不起作用。

實際上,我可以通過爲超時值休眠線程並在喚醒後關閉連接來爲statement.executeQuery()設置超時。但它的連接建立部分,我不能真正設置超時。

希望有任何幫助。

+0

這是您使用和數據的基礎驅動程序? – 2011-01-31 12:51:49

+0

我使用jdbc mysql驅動程序 – ihavprobs 2011-01-31 13:01:50

回答

4

如果沒有其他的選擇,你總是可以只運行在一個單獨的線程中調用,您中止/忽略,如果它不完成在2秒內。

編輯 這裏是什麼,我在想一個例子:

public class Dummy extends Thread { 
private volatile Connection conn = null; 
@Override 
public void run() { 
    try { 
     this.conn = DriverManager.getConnection("foobar") ; 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
} 
static public Connection getConnection() { 
    Dummy d = new Dummy() ; 
    d.start() ; 
    try { 
     Thread.sleep(2000) ; 
    } catch (InterruptedException e) {} 
    return d.conn ; 
} 
} 

然後,你可以調用靜態Dummy.getConnection()方法等地在你的代碼。一個缺點是,這個方法總是需要2秒,但是當線程完成時立即返回並不太難。

0

嘗試在連接URL或連接池上設置socketTimeout(以毫秒爲單位)(如果使用池)。注意不要將此值設置得太低,否則會覆蓋語句超時值。

try { 
    this.conn = DriverManager.getConnection("url?socketTimeout=2000") ; 
} catch (SQLException e) { 
    e.printStackTrace(); 
} 

<jdbc-connection-pool 
        connection-validation-method="table" 
        fail-all-connections="true" 
        idle-timeout-in-seconds="300" 
        is-connection-validation-required="true" 
        statement-timeout-in-seconds="2" 
        validation-table-name="dual" 
        ..... > 
    <property name="databaseName" value="...."/> 
    <property name="serverName" value="....."/> 
    <property name="User" value="....."/> 
    <property name="Password" value="......."/> 
    <property name="URL" value="jdbc:mysql://...../...."/> 
    <property name="driverClass" value="...."/> 
    <property name="socketTimeout" value="2000"/> 
</jdbc-connection-pool> 

設置這個固定的超時問題對我來說。

2

您可以使用來自Java的ExecutorService接口。以下是你需要做的一個例子。

Future<Boolean> future = executor.submit(YOUR_METHOD); 
future.get(TIMEOUT_YOU_NEED, TimeUnit.SECONDS); 
0

謝謝codebolt,我不知道這是最好的解決方案,但這對我有用。 10秒鐘超時。

public class Dummy extends Thread { 
      private volatile java.sql.Connection conn = null; 
      private boolean sleep = true; 
      @Override 
      public void run() { 
       try { 

        String driver = "net.sourceforge.jtds.jdbc.Driver"; 
        Class.forName(driver).newInstance();      
        //timeout 
        DriverManager.setLoginTimeout(10); 
        this.conn = DriverManager.getConnection(url, user, pwd); 
        sleep = false; 
       } catch (Exception e) {} 
      } 
      public java.sql.Connection getConnection() { 
       Dummy d = new Dummy() ; 
       d.start() ; 
       try { 
        for(int i=1; i<=10; i++) { 
         //Wait 1 second 
         if (d.sleep){ 
          Thread.sleep(1000); 
         } 
        } 
       } catch (InterruptedException e) {} 
       return d.conn ; 
      } 
      } 

和呼叫:

Dummy a = new Dummy(); 
connection = a.getConnection(); 
if (connection != null) {.... 
0

我在答案通過擴大和CodeBolt anpadia做出如下完整的類。它只有一個靜態方法可以接受所有需要的連接參數,包括超時時間。另外,如果它們發生,該方法也會拋出SQLException和ClassNotFoundException。

用法:

String connectionUrl = "..."; 
String user = "..."; 
String password = "..."; 
String driver = "org.postgresql.Driver"; // for example 

int timeoutInSeconds = 5; 

Connection myConnection = 
    ConnectWithTimeout.getConnection(connectionUrl, user, password, driver, timeoutInSeconds); 

下面是執行:

import java.sql.DriverManager; 
import java.sql.Connection; 
import java.sql.SQLException; 


public class ConnectWithTimeout extends Thread { 

    private static String _url; 
    private static String _user; 
    private static String _password; 
    private static String _driver; 

    private static volatile Connection _connection = null; 
    private static volatile boolean _sleep = true; 
    private static volatile SQLException _sqlException = null; 
    private static volatile ClassNotFoundException _classNotFoundException = null; 

    @Override 
    public void run() { 
     try { 
      Class.forName(_driver); 
      _connection = DriverManager.getConnection(_url, _user, _password); 
     } 
     catch (SQLException ex) { 
      _sqlException = ex; 
     } 
     catch (ClassNotFoundException ex) { 
      _classNotFoundException = ex; 
     } 
     _sleep = false; 
    } 

    public static Connection getConnection(String url, 
              String user, 
              String password, 
              String driver, 
              int timeoutInSeconds) 
     throws SQLException, ClassNotFoundException { 

     checkStringOrThrow(url,  "url"); 
     checkStringOrThrow(user,  "user"); 
     checkStringOrThrow(password, "password"); 
     checkStringOrThrow(driver, "driver"); 

     if (timeoutInSeconds < 1) { 
      throw new IllegalArgumentException(
       "timeoutInSeconds must be positive"); 
     } 

     _url = url; 
     _user = user; 
     _password = password; 
     _driver = driver; 

     ConnectWithTimeout conn = new ConnectWithTimeout(); 
     conn.start(); 

     try { 
      for (int i = 0; i < timeoutInSeconds; i++) { 
       if (_sleep) { 
        Thread.sleep(1000); 
       } 
      } 
     } 
     catch (InterruptedException ex) { 
     } 

     if (_sqlException != null) { 
      throw _sqlException; 
     } 

     if (_classNotFoundException != null) { 
      throw _classNotFoundException; 
     } 

     return _connection; 
    } 

    private static void checkStringOrThrow(String variable, String variableName) { 
     if (variable == null || variable.length() == 0) { 
      throw new IllegalArgumentException(
       "String is null or empty: " + variableName); 
     } 
    } 
} 
相關問題