首页 文章

如何强制超时为DriverManager.getConnection()方法调用?

提问于
浏览
7

我有一个应用程序,它将与MySQL Build 数据库连接并执行查询 . 有时 DriverManager.getConnection() 方法调用需要2秒,有时需要30秒 . 有没有办法在2秒后控制此方法超时?

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

实际上,我可以通过将线程休眠为超时值并在唤醒后关闭连接来设置 statement.executeQuery() 的超时 . 但它的连接 Build 部分我无法真正设置超时 .

非常感谢任何帮助 .

6 回答

  • 4

    如果没有其他选项,您可以始终只在一个单独的线程中执行调用,如果它在2秒内没有完成,您将中止/忽略该线程 .

    EDIT 这是我的想法的一个例子:

    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

    您可以使用Java中的 ExecutorService 接口 . 以下是您需要做的样本 .

    Future<Boolean> future = executor.submit(YOUR_METHOD);
    future.get(TIMEOUT_YOU_NEED, TimeUnit.SECONDS);
    
  • 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
  • 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) {....
    
  • 1

    我扩展了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);
            }
        }
    }
    

相关问题