2016-07-15 4 views
0

독립 실행 형 (웹이 아닌) Java 응용 프로그램에서 연결 풀을 사용해야합니다. 내가 일하는 곳에서는 보안 계층을 거치지 않고 API를 사용할 수 없으므로 곧 완료해야합니다. 아래는이 연결 풀을 만드는 나의 시도입니다.독립 실행 형 Java 응용 프로그램에서 연결 풀 만들기

이 코드를 단위 테스트하고 전체 응용 프로그램의 컨텍스트 내에서 수 백 번 테스트했으며 모든 경우에 테스트가 오류없이 통과했으며 각 실행의 성능이 3 천 배 미만으로 빠릅니다. 간단한 연결, 데이터를 검색, 직렬 방식으로 연결 해제; 그러나 나는 아직도이 접근법에 문제가있어 아직 내가 발굴하지 못했다는 우려는 고집 스럽다. 나는 누군가에게 아래의 코드에 관해 조언 해 주시면 감사하겠습니다. 이것은이 사이트의 첫 번째 게시물입니다. 에티켓에 실수를 저지른 경우 알려 주시기 바랍니다. 게시하기 전에이 문제에 대해이 사이트를 검색했습니다. 호출 예제 코드는 아래를 참조하십시오. 감사. --JR

package mypackage; 

import java.sql.Connection; 
import java.sql.SQLException; 
import java.util.Map; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.TimeUnit; 

/** 
* Note: This class is only instantiated once per application run. 
*  Multiple instantiations, as specified in the release notes, 
*  are not supported.  
*/ 
public class ConnectionManager { 

    // Use a blocking queue to store the database connections. 
    // The application will only be called once, by a single user, 
    // but within the application many threads will require 
    // a connection. 
    private BlockingQueue<Connection> connectionQueue = null; 

    // Load the connection queue with a user-defined number of connections. 
    // Params contains a map of all non hard-coded variables in the 
    // application. 
    public ConnectionManager(int howMany, Map<String, Object> params) { 
     Database database = new Database(); 
     connectionQueue = new ArrayBlockingQueue<Connection>(howMany); 
     for(int i = 0; i < howMany; i++) { 
      connectionQueue.add(database.getConn(params)); 
     } 
    } 

    // Return a connection from the queue, waiting up to 15 minutes to do so. 
    // 15 minutes is hard-coded because it is the standard time-out for all 
    // processes at our agency. This application must complete in less 
    // than fifteen minutes (is currently completing in thirty five seconds). 
    public Connection getConnection() { 
     Connection conn = null; 
     try { 
      conn = connectionQueue.poll(15, TimeUnit.MINUTES); 
     } 
     catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
     catch(SQLException e) { 
      e.printStackTrace(); 
     } 
     return conn; 
    } 

    // Returns a connection to the connection queue. 
    public void returnConnectionToManager(Connection conn) { 
     connectionQueue.add(conn); 
    } 

    // Called on the last line of the application program's dispatcher. 
    // Closes all active connections (which will only exist if there 
    // was a failure within one of the worker threads). 
    public void closeAllConnections() { 
     for(Connection conn : connectionQueue) { 
      try { 
       conn.close(); 
      } 
      catch(SQLException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

호출 예 :

...

private ConnectionManager cm; 

...

public Table(Map<String, Object> params, String method) { 
    ... 
    cm = (ConnectionManager) params.get("cm"); 
} 

// Execute a chunk of SQL code without requiring processing of a 
// result set. Acquires connection from pool via cm.getConnection 
// and releases connection via cm.returnConnectionToManager. 
// (Database is just a helper class with simple methods for 
// closing prepared statement, result sets, etc.) 
private void execute(String sql) { 
    PreparedStatement ps = null; 
    Connection conn = null; 
    try { 
    conn = cm.getConnection(); 
    ps = conn.prepareStatement(sql); 
    ps.execute(); 
    } 
    catch (SQLException e) { 
    e.printStackTrace(); 
    } 
    finally { 
    database.closePreparedStatement(ps); 
    cm.returnConnectionToManager(conn); 
    } 
} 
+1

저장 싱글 톤 클래스 또는 열거에 객체입니다. Prefarably enum. 이 방법으로 연결 풀에 쉽게 액세스 할 수 있으며 여러 개체를 쉽게 피할 수 있습니다. DB 트랜잭션으로 응용 프로그램 코드가 끝나면 개별 연결을 해제하는 메소드를 추가합니다. – Acewin

+3

'내가 일하는 곳에서는 보안 계층을 거치지 않고 API를 사용할 수 없습니다. '라는 소리가 나옵니다. 여기서 발명되지 않은 나쁜 경우와 같습니다. 수천 명의 사람들이 시도하고 테스트 한 오픈 소스 프레임 워크보다 사내 코드가 다소 안전하다고 생각하는 이유는 언제나 나를 놀라게합니다. –

+0

API를 지우는 코드를 작성하는 것이 아니라 IMO를 사용하는 것이 더 좋을 것입니다. – Acewin

답변

0
귀하의 코드가 좋아 보인다,하지만 하나의 심각한 문제가

, 그 API 클라이언트는 연결을 가져오고 연결을 해제해야하며, 그 중 하나는 잊어 버리고 메모리/리소스 누수가 준비되어 있어야합니다.

실행할 쿼리를 게시하는 한 곳을 만드십시오.이 곳에서 연결을 실행하고 쿼리를 실행 한 다음 풀에 연결을 반환하십시오. 연결이 반환된다는 것을 보장합니다. 단일 연결에서 여러 쿼리를 차례로 호출해야하는 경우이 메서드는 배열 또는 SQL 쿼리 목록을 순서대로 받아들입니다. 아이디어는 각 요청을 db에 캡슐화하여 모든 연결을 관리하는 것입니다. 당신이 구현할 필요가있는 (실행 연결 conn) 인터페이스를 작성 donethat 수 있습니다. 그리고 당신은 다음과 같은 개체를 걸릴 수있는 몇 가지 서비스가 그에게 연결을 제공하고 다시 연결 풀로 리소스를 해제 할 수 있습니다. 같은 뭔가 사용의

interface SqlWork { 
execute(Connection conn); 
} 

SqlWork myWork = new SqlWork() { 
    execute(Connection conn) { 
    // do you work with the conn here 
    } 
} 

class SqlExecutionService { 
    ConnectionManager cm = ...; 

    public void execute(SqlWork sqlWork) { 
     Connection conn = null; 
     try { 
     conn = cm.getConnection(); 
     sqlWork.execute(conn); 
     } catch (Your exceptions here) { 
     //serve or rethrow them 
     } 
     finally 
     { 
     if (conn!=null) { 
      cm.returnConnectionToManager(conn); 
     } 
     } 
    } 
} 

예 :

SqlExecutionService sqlExecService = ...; 
sqlExecService.execute(myWork); 
+0

고마워, 크 르지 스 토프.내가 언급하지 않은 한 가지는 아무도이 코드를 사용하지 않는다는 것입니다. 단지 실행 만 허용됩니다. 그래서 나는 그것을 오용하는 사람들에 대해 걱정할 필요가 없다. 단지 잘못 실행하는 경우 (어떤 문제가 그들에게 떨어지면, 그것은 나쁘게 들리지만 그것이 일하는 곳과 같은 종류입니다 - 모두가 그를 보호해야합니다. 왜냐하면 다른 사람은 그를 보살펴 줄 것입니다). 코드와 통찰력을 가져 주셔서 감사합니다. 매우 감사. – Jack

+0

그게 유효한 지점 인 것 같습니다 :)하지만이 approch가 미래에 시간을 절약 할 것이라고 확신합니다. 자동이 아닌 경우 무언가를하는 것을 자주 잊어 버렸습니다. –

관련 문제