program story

JDBC에서 연결 풀을 설정하는 방법은 무엇입니까?

inputbox 2020. 8. 13. 08:20
반응형

JDBC에서 연결 풀을 설정하는 방법은 무엇입니까?


누구든지 JDBC 연결 풀을 설정하는 방법에 대한 예제 나 링크를 제공 할 수 있습니까?

Google 검색에서 나는 이것을하는 많은 다른 방법을 볼 수 있으며 다소 혼란 스럽습니다.

궁극적으로 java.sql.Connection객체 를 반환하는 코드가 필요 하지만 시작하는 데 문제가 있습니다. 어떤 제안이라도 환영합니다.

업데이트 : 합니까하지 javax.sql또는 java.sql풀 된 접속의 구현이? 왜 이것을 사용하는 것이 최선이 아닐까요?


독립형 연결 풀이 필요한 경우 DBCP 보다 C3P0선호합니다 ( 이전 답변 에서 언급 했음). 부하가 심한 경우 DBCP에 너무 많은 문제가 있습니다. C3P0을 사용하는 것은 매우 간단합니다. 로부터 문서 :

ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("swaldman");
cpds.setPassword("test-password");

// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);

// The DataSource cpds is now a fully configured and usable pooled DataSource 

그러나 응용 프로그램 서버 내부에서 실행하는 경우 제공되는 기본 제공 연결 풀을 사용하는 것이 좋습니다. 이 경우이를 구성하고 (애플리케이션 서버 문서 참조) JNDI를 통해 데이터 소스를 검색해야합니다.

DataSource ds = (DataSource) new InitialContext().lookup("jdbc/myDS");

일반적으로 연결 풀이 필요한 경우 일부 관리 환경에서 실행되는 애플리케이션, 즉 애플리케이션 서버 내부에서 실행중인 애플리케이션을 작성합니다. 이 경우 다른 옵션을 시도하기 전에 애플리케이션 서버가 제공하는 연결 풀링 기능확인 하십시오 .

즉시 사용 가능한 솔루션은 나머지 애플리케이션 서버 시설과 가장 잘 통합됩니다. 그러나 응용 프로그램 서버 내에서 실행하지 않는 경우 Apache Commons DBCP 구성 요소를 권장합니다 . 널리 사용되며 대부분의 응용 프로그램에 필요한 모든 기본 풀링 기능을 제공합니다.


바퀴를 재발 명하지 마십시오.

즉시 사용 가능한 타사 구성 요소 중 하나를 사용해보십시오.

  • Apache DBCP- 이것은 Tomcat에서 내부적으로 사용되며 실제로는 사용자가 사용합니다.
  • c3p0

Apache DBCP에는 javax.sql.DataSource 풀링을 설정하는 방법에 대한 다른 예제가 있습니다. 다음은 시작하는 데 도움 이되는 하나의 샘플 입니다.


commons-dbcp 라이브러리를 사용하는 것이 좋습니다 . 사용 방법에 대한 많은 예제가 나열되어 있으며 여기에 간단한 이동 링크가 있습니다. 사용법은 매우 간단합니다.

 BasicDataSource ds = new BasicDataSource();
 ds.setDriverClassName("oracle.jdbc.driver.OracleDriver")
 ds.setUsername("scott");
 ds.setPassword("tiger");
 ds.setUrl(connectURI);
 ...
 Connection conn = ds.getConnection();

데이터 소스는 한 번만 작성하면되므로 작성 방법을 모르는 경우 문서를 읽으십시오. 자원이 누출되지 않도록 JDBC 문을 올바르게 작성하는 방법을 알지 못하는 경우이 Wikipedia 페이지 를 읽을 수도 있습니다 .


HikariCP

현대적이고 빠르며 간단합니다. 나는 모든 새로운 프로젝트에 그것을 사용합니다. 나는 C3P0보다 많이 선호하고 다른 풀을 너무 잘 모릅니다.


내가 일하는 곳에서 사용하는 앱 서버 (내가 기억하는 것처럼 Oracle Application Server 10g)에서는 풀링이 앱 서버에 의해 처리됩니다. 우리는이 검색 javax.sql.DataSource기호가있는 JNDI 조회를 사용 javax.sql.InitialContext.

이렇게 됐어

try {     
   context = new InitialContext();
   jdbcURL = (DataSource) context.lookup("jdbc/CachedDS");
   System.out.println("Obtained Cached Data Source ");
}
catch(NamingException e)   
{  
    System.err.println("Error looking up Data Source from Factory: "+e.getMessage());
}

(우리는이 코드를 작성하지 않았으며이 문서 에서 복사했습니다 .)


  • 풀링 메커니즘은 객체를 미리 생성하는 방법입니다. 클래스가로드 될 때.
  • performance[Object-Data에 대한 작업을 수행하기 위해 동일한 객체를 재사용함으로써] 및 memory[많은 객체를 할당 및 할당 해제하면 상당한 메모리 관리 오버 헤드가 발생 함] 응용 프로그램이 향상됩니다 .
  • 동일한 Object를 사용하므로 가비지 수집 부하를 줄이므로 객체 정리가 필요하지 않습니다.

«풀링 [ Object풀, String상수 풀, Thread풀, 연결 풀]

문자열 상수 풀

  • 문자열 리터럴 풀은 각 고유 한 문자열 값의 복사본을 하나만 유지합니다. 불변이어야합니다.
  • 인턴 메소드가 호출되면 equals 메소드를 사용하여 풀에서 동일한 콘텐츠의 객체 가용성을 확인합니다. «Pool에서 String-copy를 사용할 수있는 경우 참조를 반환합니다. «그렇지 않으면 String 개체가 풀에 추가되고 참조를 반환합니다.

예 : 풀에서 고유 개체 를 확인하는 문자열 입니다.

public class StringPoolTest {
    public static void main(String[] args) { // Integer.valueOf(), String.equals()
        String eol = System.getProperty("line.separator"); //java7 System.lineSeparator();

        String s1 = "Yash".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s1, s1.hashCode(), System.identityHashCode(s1));
        String s2 = "Yas"+"h".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s2, s2.hashCode(), System.identityHashCode(s2));
        String s3 = "Yas".intern()+"h".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s3, s3.hashCode(), System.identityHashCode(s3));
        String s4 = "Yas"+"h";
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s4, s4.hashCode(), System.identityHashCode(s4));
    }
}

유형 4 사용하여 연결 풀 드라이버를 제 3 자 라이브러리를 사용하여 [ DBCP2, c3p0, Tomcat JDBC]

Type 4 - The Thin driver converts JDBC calls directly into the vendor-specific database protocol Ex[Oracle - Thick, MySQL - Quora]. 위키

연결 풀 메커니즘에서 클래스가로드되면 physical JDBC connection개체를 가져와 사용자에게 래핑 된 물리적 연결 개체를 제공합니다. PoolableConnection실제 연결을 감싸는 래퍼입니다.

  • getConnection()연결 개체 풀 에서 무료 래핑 연결 중 하나를 선택 하고 반환합니다.
  • close() 닫는 대신 래핑 된 연결을 풀로 다시 반환합니다.

예 : Java 7 [ try-with-resources] 과 함께 ~ DBCP2 연결 풀 사용

public class ConnectionPool {
    static final BasicDataSource ds_dbcp2 = new BasicDataSource();
    static final ComboPooledDataSource ds_c3p0 = new ComboPooledDataSource();
    static final DataSource ds_JDBC = new DataSource();

    static Properties prop = new Properties();
    static {
        try {
            prop.load(ConnectionPool.class.getClassLoader().getResourceAsStream("connectionpool.properties"));

            ds_dbcp2.setDriverClassName( prop.getProperty("DriverClass") );
            ds_dbcp2.setUrl( prop.getProperty("URL") );
            ds_dbcp2.setUsername( prop.getProperty("UserName") );
            ds_dbcp2.setPassword( prop.getProperty("Password") );
            ds_dbcp2.setInitialSize( 5 );

            ds_c3p0.setDriverClass( prop.getProperty("DriverClass") );
            ds_c3p0.setJdbcUrl( prop.getProperty("URL") );
            ds_c3p0.setUser( prop.getProperty("UserName") );
            ds_c3p0.setPassword( prop.getProperty("Password") );
            ds_c3p0.setMinPoolSize(5);
            ds_c3p0.setAcquireIncrement(5);
            ds_c3p0.setMaxPoolSize(20);

            PoolProperties pool = new PoolProperties();
            pool.setUrl( prop.getProperty("URL") );
            pool.setDriverClassName( prop.getProperty("DriverClass") );
            pool.setUsername( prop.getProperty("UserName") );
            pool.setPassword( prop.getProperty("Password") );
            pool.setValidationQuery("SELECT 1");// SELECT 1(mysql) select 1 from dual(oracle)

            pool.setInitialSize(5);
            pool.setMaxActive(3);
            ds_JDBC.setPoolProperties( pool );
        } catch (IOException e) {   e.printStackTrace();
        } catch (PropertyVetoException e) { e.printStackTrace(); }
    }

    public static Connection getDBCP2Connection() throws SQLException {
        return ds_dbcp2.getConnection();
    }

    public static Connection getc3p0Connection() throws SQLException {
        return ds_c3p0.getConnection();
    }

    public static Connection getJDBCConnection() throws SQLException {
        return ds_JDBC.getConnection();
    }
}
public static boolean exists(String UserName, String Password ) throws SQLException {
    boolean exist = false;
    String SQL_EXIST = "SELECT * FROM users WHERE username=? AND password=?";
    try ( Connection connection = ConnectionPool.getDBCP2Connection();
          PreparedStatement pstmt = connection.prepareStatement(SQL_EXIST); ) {
        pstmt.setString(1, UserName );
        pstmt.setString(2, Password );

        try (ResultSet resultSet = pstmt.executeQuery()) {
            exist = resultSet.next(); // Note that you should not return a ResultSet here.
        }
    }
    System.out.println("User : "+exist);
    return exist;
}

jdbc:<DB>:<drivertype>:<HOST>:<TCP/IP PORT>:<dataBaseName> jdbc:oracle:thin:@localhost:1521:myDBName jdbc:mysql://localhost:3306/myDBName

connectionpool.properties

URL         : jdbc:mysql://localhost:3306/myDBName
DriverClass : com.mysql.jdbc.Driver
UserName    : root
Password    :

응용 프로그램 : 모든 연결이 닫 혔을 때 연결 문제를 방지하기 위해 [MySQL "wait_timeout"기본 8 시간] 기본 DB와의 연결을 다시 시작합니다.

testOnBorrow = true 및 validationQuery = "SELECT 1"을 설정하여 모든 연결을 테스트 할 수 있으며 더 이상 사용되지 않는 MySQL 서버용 autoReconnect를 사용하지 마십시오. 발행물

===== ===== context.xml ===== =====
<?xml version="1.0" encoding="UTF-8"?>
<!-- The contents of this file will be loaded for a web application -->
<Context>
    <Resource name="jdbc/MyAppDB" auth="Container" 
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
        type="javax.sql.DataSource" 

        initialSize="5" minIdle="5" maxActive="15" maxIdle="10"

        testWhileIdle="true"
            timeBetweenEvictionRunsMillis="30000"

        testOnBorrow="true"
            validationQuery="SELECT 1"
            validationInterval="30000"


        driverClassName="com.mysql.jdbc.Driver" 
        url="jdbc:mysql://localhost:3306/myDBName" 
        username="yash" password="777"
    />
</Context>

===== ===== web.xml ===== =====
<resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/MyAppDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
===== ===== DBOperations ===== =====
servlet «   init() {}
Normal call used by sevlet  « static {}

static DataSource ds;
static {
    try {
        Context ctx=new InitialContext();
        Context envContext = (Context)ctx.lookup("java:comp/env");
        ds  =   (DataSource) envContext.lookup("jdbc/MyAppDB");
    } catch (NamingException e) {   e.printStackTrace();    }
}

다음을 참조하십시오.


In late 2017 Proxool, BoneCP, C3P0, DBCP are mostly defunct at this time. HikariCP (created in 2012) seems promising, blows the doors off anything else I know of. http://www.baeldung.com/hikaricp

Proxool has a number of issues:
- Under heavy load can exceed max number of connections and not return below max
- Can manage to not return to min connections even after connections expire
- Can lock up the entire pool (and all server/client threads) if it has trouble connecting to the database during HouseKeeper thread (does not use .setQueryTimeout)
- HouseKeeper thread, while having connection pool lock for its process, requests the Prototyper thread to recreate connections (sweep) which can result in race condition/lockup. In these method calls the last parameter should always be sweep:false during the loop, only sweep:true below it.
- HouseKeeper only needs the single PrototypeController sweep at the end and has more [mentioned above]
- HouseKeeper thread checks for testing of connections before seeing what connections may be expired [some risk of testing expired connection that may be broken/terminated through other timeouts to DB in firewall, etc.]
- The project has unfinished code (properties that are defined but not acted upon)
- The Default max connection life if not defined is 4 hours (excessive)
- HouseKeeper thread runs every five seconds per pool (excessive)

You can modify the code and make these improvements. But as it was created in 2003, and updated in 2008, its lacking nearly 10 years of java improvements that solutions like hikaricp utilize.


As answered by others, you will probably be happy with Apache Dbcp or c3p0. Both are popular, and work fine.

Regarding your doubt

Doesn't javax.sql or java.sql have pooled connection implementations? Why wouldn't it be best to use these?

They don't provide implementations, rather interfaces and some support classes, only revelant to the programmers that implement third party libraries (pools or drivers). Normally you don't even look at that. Your code should deal with the connections from your pool just as they were "plain" connections, in a transparent way.


Vibur DBCP is another library for that purpose. Several examples showing how to configure it for use with Hibernate, Spring+Hibernate, or programatically, can be found on its website: http://www.vibur.org/

Also, see the disclaimer here.


Apache Commons has a library for that purpose: DBCP. Unless you have strange requirements around your pools, I'd use a library as it's bound to be trickier and more subtle than you would hope.


You should consider using UCP. Universal Connection Pool (UCP) is a Java connection pool. It is a features rich connection pool and tightly integrated with Oracle's Real Application Clusters (RAC), ADG, DG databases.

Refer to this page for more details about UCP.


MiniConnectionPoolManager is a one-java-file implementation, if you're looking for an embeddable solution and are not too concerned about performances (though I haven't tested it in that regard).

It is multi-licensed EPL, LGPL and MPL.

Its documentation also gives alternatives worth checking (on top of DBCP and C3P0):

참고URL : https://stackoverflow.com/questions/2835090/how-to-establish-a-connection-pool-in-jdbc

반응형