반응형
1. Properties 파일의 개념 및 특징
1) Properties 파일
- 프로그램 실행에 필요한 값을 제공하기 위한 텍스트 파일
- 확장자 : ~.properties
- 프로그램을 변경하지 않고 Properties 파일만을 변경하여 프로그램의 실행 결과 변경 가능
- 프로그램의 유지보슈 효율성 증가
2) Properties 파일로 제공되는 "값"
- 문자열만 가능
- MAP은 원래 제네릭을 통해 "원하는 값"을 저장가능하지만,
- Properties는 오직 문자열만 가능!!!
3) Properties 파일에서는..
- 영문자 , 숫자 , 일부 특수문자를 제외한 나머지 문자는 유니코드로 변환되어 처리
4) Properties 파일
user.properties
#Comment - \\uC124\\uBA85\\uBB38
#Properties File >> Configuration File
#Name = Value
id = abc123
password = 123456
name = \\uD64D\\uAE38\\uB3D9
4)user.properties 파일에 저장된 값을 얻어와 출력하는 프로그램
PropertiesApp.java
package xyz.itwill.dbcp;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
//Properties 파일 : 프로그램 실행에 필요한 값을 제공하기 위한 텍스트 파일 - 확장자 : ~.properties
// => 프로그램을 변경하지 않고 Properties 파일의 내용을 변경하여 프로그램의 실행 결과 변경 가능
// => 프로그램의 유지보수 효율성 증가
// => Properties 파일로 제공되는 값은 문자열만 가능
// => Properties 파일에서는 영문자,숫자,일부 특수문자를 제외한 나머지 문자는 유니코드로 변환되어 처리
//[user.properties 파일]에 저장된 값을 얻어와 출력하는 프로그램 작성
public class PropertiesApp {
public static void main(String[] args) throws IOException {
/*
//방법1. 비권장
//1. Properties 파일을 읽기 위한 파일 입력스트림 생성
//=> Properties 파일의 경로를 제공받아 FileInputStream 클래스로 객체(입력스트림) 생성
// => 프로그램 배포시 파일 경로 문제점 발생 가능
FileInputStream in = new FileInputStream("src/xyz/itwill/dbcp/user.properties"); //OK지만, 배포시문제
//FileInputStream in = new //FileInputStream("xyz/itwill/dbcp/user.properties"); //ERROR
*/
//방법2. 권장
//1. 클래스명.class : Class 파일을 이용하여 Class 객체(Clazz)를 표현하는 방법
//Class.getClassLoader() : 클래스를 읽어 메모리에 저장하는 ClassLoader 객체를 반환하는 메소드
//ClassLoader.getResourceAsStream(String name) : 리소스 파일에 대한 입력스트림을 생성하여 반환하는 메소드
// => 프로그램 배포시 파일 경로 문제점 발생 없음
InputStream in = PropertiesApp.class.getClassLoader().getResourceAsStream("xyz/itwill/dbcp/user.properties");
/*
클래스 객체 만들기 -> 클래스 로더 뽑아내기 -> getResourceAsStream()로 리소스 파일에 대한 입력스트림을 생성받기이용받기
메인메소드 내라 이런식으로 경로 알아냄, 메인메소드가 아니라면 Object.getClass()메소드 이용하는 것이 더 편함
*/
//2. java.util 패키지의 Properties 클래스로 객체 생성
//Properties 객체 : Properties 파일의 내용을 전달받아 저장하기 위한 객체
//=>Map 인터페이스를 상속받은 자료구조 클래스
//=>다수의 엔트리(entry - Key 와 Value) 저장
Properties properties = new Properties();
/*
Properties클래스를 사용하는 이유!
Properties파일을 읽어들여 Properties파일이 제공하는 값들을 엔트리로 제공받아 저장하기 위해 사용하는 것인데,
properties.put()메소드를 사용하는 것은 파일에 값을 저장하는 것이니 비효율적!!!!
이럴꺼면 HashMap 이용해라
*/
//3.
//**Properties.load(InputStream in): 입력스트림을 사용하여 Properties 파일의 모든 이름(name)과 값(value)을 제공받아 Properties 객체의 엔트리로 저장하는 메소드
properties.load(in);
//4.
//Properties.get(String key) : Properties 객체에 저장된 엔트리에서 맵키(MapKey)를 전달받아 맵값(MapValue)을 반환하는 메소드
// => Object 객체를 반환하므로 명시적 객체 형변환 후 사용 가능
String id = (String)properties.get("id");
String password = (String)properties.get("password");
String name = (String)properties.get("name");
System.out.println("아이디 = "+id);
System.out.println("비밀번호 = "+password);
System.out.println("이름 = "+name);
}
}
//아이디 = abc123
//비밀번호 = 123456
//이름 = 홍길동
2. DBCP(DataBase Connection Pool)의 개념
1) DBCP (DataBase Connection Pool)
- 다수의 Connection 객체를 미리 생성하여 저장하고 Connection 객체를 반환하는 기능을 제공하는 클래스
- 즉, 미리 DB서버에 접속된 Connection 객체를 미리 생성하여 저장한 것
- 앞서 만들었던 ConnectionFactory 클래스 는 ConnectionFactory.getConnection( )메소드 호출해 Connection 객체 생성했지만,
- DBCP 는 Connection 객체를 미리 생성해두고, ConnectionPool.getInstance()메소드나 ConnectionPool.getPoolDataSource()메소드로 반환받아 사용함
2) DBCP의 장점
- Connection객체를 미리 생성하여 사용하므로 JDBC 프로그램의 실행 속도 증가
- Connection객체를 생성하기 위한 정보의 변경 용이 - 유지보수의 효율성 증가
- Connection객체의 갯수 제한 가능
3) DBCP (connectionPool) -> preparedStatement
- 오라클그룹에서 제공해주는 connectionPool클래스
- 아파치그룹에서 제공해주는 connectionPool클래스
- 스프링그룹에서 제공해주는 connectionPool클래스
3. [규칙없음] 회사가 제공해주는ConnectionPool클래스 & 비표준화된ConnectionPool
1) 회사가 제공하는 DBCP 기능 - db.properties & ConnectionPool.java
- ConnectionPool.java
- 비표준화된 ConnectionPool 클래스임
- 회사에서 그 회사만이 사용하는 ConnectionPool 클래스를 제공해준것임
- 즉, 회사마다 사용 ConnectionPool 다름
- db.properties
- Connetion객체는 미리 2개 생성되어 있음
- Connetion객체는 최대 3개까지 생성 가능함
2) properties파일
db.properties
#########################################
### ConnectionPool Configuration file ###
#########################################
url = jdbc:oracle:thin:@localhost:1521:XE
user = scott
passwd = tiger
driver = oracle.jdbc.driver.OracleDriver
initialCons = 2
maxCons = 3
block = true
timeout = 10000
3) ConnectionPool
ConnectionPool.java
package xyz.itwill.dbcp;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
//Connection Pooling 기능을 구현한 클래스
public final class ConnectionPool {
// Singleton
private static ConnectionPool instance;
// Storage for the unused connections.
private Vector<Connection> free;
// Storage for the allocated connections.
private Vector<Connection> used;
// Connection information.
private String driver;
private String url;
private String user;
private String password;
// Initial Connections
private int initialCons = 0;
// Maximum number of concurrent connections allowed.
private int maxCons = 0;
// The number of connection that have been created.
private int numCons = 0;
// Whether to block until a connection is free when maxCons are in use.
private boolean block;
// Timeout waiting for a connection to be released when blocking.
private long timeout;
// Whether we should re-use connections or not
private boolean reuseCons = true;
/**
* Creates a new <code>ConnectionPool</code> with defaults for
* <code>Connection</code> characteristics. Specifies the url, user and
* password for <code>Connections</code> and the characteristics of the
* pool.
*
* @param url
* The url for the database, as in jdbc:<em>subprotocol</em>:
* <em>subname</em>.
* @param user
* The user to connect to the database as.
* @param password
* The user's password.
* @param initialCons
* The number of connections to create now.
* @param maxCons
* The maximum number of connections allowed. A value <= 0 means
* "no limit". If maxCons > 0 and maxCons < initialCons then
* maxCons takes precedence.
* @param block
* If a request for a connection should block until a connection
* is released when none are available and maxCons has been
* reached.
* @param timeout
* Maximum time to wait for a connection to be released when
* maxCons are in use.
* @exception SQLException
* if a connection could not be established, this is the
* exception thrown by DriverManager.
* @see java.sql.Connection
* @see java.sql.DriverManager
* @see java.sql.DriverManager#getConnection(String, String, String)
**/
private ConnectionPool() throws SQLException {
loadConf();
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// maxCons has precedence over initialCons
if (maxCons > 0 && maxCons < initialCons)
initialCons = maxCons;
// Create vectors large enough to store all the connections we make now.
free = new Vector<Connection>(initialCons);
used = new Vector<Connection>(initialCons);
// Create some connections.
while (numCons < initialCons) {
addConnection();
}
}
public static ConnectionPool getInstance() throws SQLException {
if (instance == null) {
synchronized (ConnectionPool.class) {
if (instance == null) {
instance = new ConnectionPool();
}
}
}
return instance;
}
private void loadConf() {
ClassLoader cl = getClass().getClassLoader();
InputStream in=cl.getResourceAsStream("xyz/itwill/dbcp/db.properties");
Properties p = new Properties();
try {
p.load(in);
} catch(IOException e) {
e.printStackTrace();
}
this.driver=(String)p.get("driver");
this.url = (String)p.get("url");
this.user = (String)p.get("user");
this.password = (String)p.get("passwd");
this.initialCons = Integer.parseInt((String)p.get("initialCons"));
this.maxCons = Integer.parseInt((String)p.get("maxCons"));
this.block = Boolean.getBoolean((String)p.get("block"));
this.timeout = Long.parseLong((String)p.get("timeout"));
}
/**
* Closes all unallocated <code>connections</code>, allocated
* <code>connections</code> are marked for closing when they are released.
*
* @see #freeConnection
* @see java.sql.Connection#close
**/
@SuppressWarnings("unchecked")
public synchronized void closeAll() {
Enumeration<Connection> cons = ((Vector<Connection>)free.clone()).elements();
while (cons.hasMoreElements()) {
Connection con = (Connection) cons.nextElement();
free.removeElement(con);
numCons--;
try {
con.close();
} catch (SQLException e) {
// The Connection appears to be broken anyway, so we will ignore it
e.printStackTrace();
}
}
// Move allocated connections to a list of connections that are closed
// when they are released.
cons = ((Vector<Connection>) used.clone()).elements();
while (cons.hasMoreElements()) {
Connection con = (Connection) cons.nextElement();
used.removeElement(con);
}
}
/**
* Gets the <code>block</code> property for the pool. The block values
* specifies whether a <code>getConnection()</code> request should wait for
* a <code>connection</code> to be release if the maximum allowed are all in
* use.
*
* @return The block property.
* @see #setBlock
* @see #getConnection
**/
public boolean getBlock() {
return block;
}
/**
* Gets a <code>Connection</code> from the pool.
*
* @return A connection
* @exception ConnectionPoolException
* if the maximum number of allowed connections are all in
* use, and, the "pool" is not blocking or the timeout
* expired when waiting.
* @exception SQLException
* if all existing connections are in use and a new one could
* not be created, this is the exception thrown by
* DriverManger when attempting to get a new connection.
* @see java.sql.DriverManager
**/
public Connection getConnection() throws SQLException {
return getConnection(this.block, timeout);
}
/**
* Gets a <code>Connection</code> from the pool.
*
* @param block
* If a request for a connection should block until a connection
* is released when none are available and maxCons has been
* reached, overrides the value specified at construction.
* @param timeout
* Maximum time to wait for a connection to be released when
* maxCons are in use, overrides the values specified at
* construction.
* @return A connection
* @exception ConnectionPoolException
* if the maximum number of allowed connections are all in
* use, and, the "pool" is not blocking or the timeout
* expired when waiting.
* @exception SQLException
* if all existing connections are in use and a new one could
* not be created, this is the exception thrown by
* DriverManger when attempting to get a new connection.
* @see java.sql.DriverManager
**/
public synchronized Connection getConnection(boolean block, long timeout) throws SQLException {
if (free.isEmpty()) {
// None left, do we create more?
if (maxCons <= 0 || numCons < maxCons) {
addConnection();
} else if (block) {
try {
long start = System.currentTimeMillis();
do {
wait(timeout);
if (timeout > 0) {
timeout -= System.currentTimeMillis() - start;
if (timeout == 0) {
timeout -= 1;
}
}
} while (timeout >= 0 && free.isEmpty() && maxCons > 0 && numCons >= maxCons);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Did anyone release a connection while we were waiting?
if (free.isEmpty()) {
/*
* OK, nothing on the free list, but someone may have
* released a connection that they closed, so the free list
* is empty but numCons is now < maxCons and we can create a
* new connection.
*/
if (maxCons <= 0 || numCons < maxCons) {
addConnection();
} else {
throw new SQLException("Timeout waiting for a connection to be released");
}
}
} else {
// No connections left and we don't wait for more.
throw new SQLException("Maximum number of allowed connections reached");
}
}
// If we get this far at least one connection is available.
Connection con;
synchronized (used) {
con = (Connection) free.lastElement();
// Move this connection off the free list
free.removeElement(con);
used.addElement(con);
}
return con;
}
/**
* Gets the <code>maxCons</code> property for the pool. The maxCons values
* specifies the maximum number of <code>Connections</code> that can be
* allocated from the pool at any one time.
*
* @return The maxCons property.
* @see #getConnection
**/
public int getMaxCons() {
return maxCons;
}
/**
* Gets the reuseConnections property for the pool.
*
* @see #setReuseConnections
**/
public boolean getReuseConnections() {
return reuseCons;
}
/**
* Gets the <code>timeout</code> property for the pool. The timeout values
* specifies how long to wait for a <code>Connection</code> to be release if
* the maximum allowed are all in use when <code>getConnection()</code> is
* called and <code>block</code> is true.
*
* @return The timeout property.
* @see #setTimeout
**/
public long getTimeout() {
return timeout;
}
/**
* Gets the <code>url</code> property for the pool. This property is the url
* for <code>Connections</code> opened by this pool.
*
* @return The url property.
**/
public String getUrl() {
return url;
}
/**
* Release a connection back to the pool. Apps should take care not to use a
* <code>Connection</code> after it has been released as it may well be in
* use somewhere else, in which case the effects are undefined.
* <p>
* If an app has cause to close a <code>Connection</code> then it should
* still be released so that the count of active transactions is correct and
* a new <code>Connection</code> can be created to take its place.
* <p>
* A rollback is performed on the <code>Connection</code> so if autoCommit
* is false any changes made that have not been committed will be lost.
*
* @param con
* The Connection to put back in the pool.
* @exception UnownedConnectionException
* if the Connection did not come from this pool.
* @see #getConnection
**/
public synchronized void freeConnection(Connection con) throws SQLException {
boolean reuseThisCon = reuseCons;
if (used.contains(con)) {
// Move this connection from the used list to the free list
used.removeElement(con);
numCons--;
} else {
throw new SQLException("Connection " + con + " did not come from this ConnectionPool");
}
try {
if (reuseThisCon) {
free.addElement(con);
numCons++;
} else {
con.close();
}
// Wake up a thread waiting for a connection
notify();
} catch (SQLException e) {
/*
* The Connection seems to be broken, but it's off the used list and
* the connection count has been decremented.
*/
// Just to be sure
try {
con.close();
} catch (Exception e2) {
// we're expecting an SQLException here
}
notify();
}
}
/**
* Sets the <code>block</code> property for the pool. The block values
* specifies whether a <code>getConnection()</code> request should wait for
* a <code>Connection</code> to be release if the maximum allowed are all in
* use.
* <p>
* Setting <code>block</code> to false will have no effect on any connection
* requests that have already begin to wait for a connection.
*
* @param block
* The block property.
* @see #getBlock
**/
public void setBlock(boolean block) {
this.block = block;
}
/**
* Sets the reuseConnections property on the pool. If this property is false
* then whenever a <code>Connection</code> is released it will be closed.
*
* @see #getReuseConnections
* @see #freeConnection
* @see java.sql.Connection
* @see java.sql.Connection#close
**/
public synchronized void setReuseConnections(boolean reuseCons) {
this.reuseCons = reuseCons;
}
/**
* Sets the <code>timeout</code> property for the pool. The timeout values
* specifies how long to wait for a <code>Connection</code> to be release if
* the maximum allowed are all in use when <code>getConnection()</code> is
* called and <code>block</code> is true.
* <p>
* Setting <code>timeout</code> will have no effect on any
* <code>Connection</code> requests that have already begin to wait for a
* <code>Connection</code>.
*
* @return The timeout property.
* @see #getTimeout
**/
public void setTimeout(long timeout) {
this.timeout = timeout;
}
/**
* Adds a new <code>Connection</code> to the pool.
*
* @exception SQLException
* if a connection could not be established.
**/
private void addConnection() throws SQLException {
free.addElement(getNewConnection());
}
/**
* Gets a new <code>Connection</code>.
*
* @exception SQLException
* if a connection could not be established.
**/
private Connection getNewConnection() throws SQLException {
Connection con = null;
//System.out.println("About to connect to " + url);
try {
con = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
++numCons;
return con;
}
}
4) 실행 프로그램
ConnectionPoolApp.java
package xyz.itwill.dbcp;
import java.sql.Connection;
import java.sql.SQLException;
//DBCP(DataBase Connection Pool) : 다수의 Connection 객체를 미리 생성하여 저장하고 Connection 객체를 반환하는 기능을 제공하는 클래스
// => Connection 객체를 미리 생성하여 사용하므로 JDBC 프로그램의 실행 속도 증가
// => Connection 객체를 생성하기 위한 정보의 변경 용이 - 유지보수의 효율성 증가
// => Connection 객체의 갯수 제한 가능
public class ConnectionPoolApp {
public static void main(String[] args) throws SQLException {
//🍓1. 미리 만들어진 Connection객체 반환받기
//ConnectionPool 클래스의 생성자가 은닉화 선언되어 new 연산자로 생성자를 호출하여 객체 생성 불가능
//ConnectionPool cp = new ConnectionPool(); --ERROR
//ConnectionPool.getInstance() 메소드를 호출하여 ConnectionPool 객체를 반환받아 저장
// => ConnectionPool 객체에는 다수의 Connection 객체가 미리 생성되어 저장되어있음
// => 프로그램에서 ConnectionPool 객체가 하나만 제공되도록 싱글톤(Singleton) 클래스 작성
ConnectionPool cp = ConnectionPool.getInstance();
//🍓2. 하나의 Connection객체만 사용하고 반납 반복
//ConnectionPool 객체에 저장된 Connection 객체 중 하나를 반환받아 저장
Connection con1 = cp.getConnection();
System.out.println("con1 ="+con1); //con1 =oracle.jdbc.driver.T4CConnection@5f8e8a9d
cp.freeConnection(con1); //사용한 Connection객체를 ConnectionPool객체에게 다시 반납 처리
Connection con2 = cp.getConnection();
System.out.println("con2 ="+con2); //con2 =oracle.jdbc.driver.T4CConnection@5f8e8a9d
cp.freeConnection(con2);
Connection con3 = cp.getConnection();
System.out.println("con3 ="+con3); //con3 =oracle.jdbc.driver.T4CConnection@5f8e8a9d
cp.freeConnection(con3);
//🍓3. 사용하고 반납하지 않으면 서로다른 Connection객체 사용함
Connection con1 = cp.getConnection();
System.out.println("con1 ="+con1); //con1 =oracle.jdbc.driver.T4CConnection@5f8e8a9d
Connection con2 = cp.getConnection();
System.out.println("con2 ="+con2); //con2 =oracle.jdbc.driver.T4CConnection@d35dea7
Connection con3 = cp.getConnection();
System.out.println("con3 ="+con3); //con3 =oracle.jdbc.driver.T4CConnection@38467116
Connection con4 = cp.getConnection();
System.out.println("con4 ="+con4); //ERROR, Connetion객체는 최대 3개까지 생성 가능
}
}
4. [규칙있음] PoolDataSource클래스 & 표준화된ConnectionPool
1) DataSource 인터페이스
- javax.sql패키지 내 DataSource 인터페이스
- DBCP 클래스가 상속받음 - 메소드가 동일한 형식으로 작성되도록 규칙 제공
2) PoolDataSource 클래스
- 오라클에서 제공해주는 DBCP클래스
- https://www.oracle.com 오라클 사이트에서 UCP 라이브러리 파일(ucp11.jar)을 다운로드 받아 프로젝트에 빌드 처리하기
- oracle.ucp.jdbc패키지 내 PoolDataSource 클래스
- oracle회사 > UCP(Universal Connection Pool)라이브러리 > DBCP 기능의 클래스
3) 실행프로그램
DataSourceApp.java
package xyz.itwill.dbcp;
import java.sql.Connection;
import java.sql.SQLException;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
//javax.sql.DataSource : DBCP 클래스가 작성시 상속받기 위한 인터페이스
// => DBCP 클래스의 메소드가 동일한 형식으로 작성되도록 규칙 제공
//UCP(Universal Connection Pool) 라이브러리에서 제공하는 DBCP 기능의 클래스를 이용한 JDBC 프로그램 작성
// => <https://www.oracle.com> Site에서 UCP 라이브러리 파일(ucp11.jar)을 다운로드 받아 프로젝트에 빌드 처리
public class DataSourceApp {
public static void main(String[] args) throws SQLException{
//🍑 PoolDataSource객체 반환받기 : PoolDataSource 객체로 미리 만들어진 Connection객체 반환받기 가능함
//PoolDataSource 객체 : DBCP 기능을 제공하는 객체 - 이 객체 안에는 미리 Connection들이 여러개 만들어져있음
//PoolDataSource.getPoolDataSource() : PoolDataSource 객체를 반환하는 메소드
//=>Factory 클래스 : 객체를 안정적으로 생성하여 반환하는 기능을 제공하는 클래스
//PoolDataSource pds = new PoolDataSourceImpl(); //비권장
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource(); //권장
//🍑 PoolDataSource객체의 메소드 이용하기
//PoolDataSource.setConnectionFactoryClassName(String driver) : JDBC Driver 클래스를 변경하는 메소드
pds.setConnectionFactoryClassName("oracle.jdbc.driver.OracleDriver");
//PoolDataSource.setURL(String url) : 접속 DBMS 서버의 URL 주소를 변경하는 메소드
pds.setURL("jdbc:oracle:thin:@localhost:1521:xe");
//PoolDataSource.setUser(String user) : DBMS 사용자명을 변경하는 메소드
pds.setUser("scott");
//PoolDataSource.setPassword(String password) : DBMS 사용자명의 비밀번호를 변경하는 메소드
pds.setPassword("tiger");
//🍑 PoolDataSource객체에 저장된 Connection 객체의 갯수를 제한하기 위한 메소드 호출
//=> 메소드 호출하지 않을 경우 PoolDataSource객체에 저장된 기본값을 사용하여 Connection 갯수 제한
//PoolDataSource.setInitialPoolSize(int size) : 최초로 생성되는 Connection 객체의 갯수를 변경하는 메소드
pds.setInitialPoolSize(2);
//PoolDataSource.setMaxPoolSize(int size) : 최대로 생성되는 Connection 객체의 갯수를 변경하는 메소드
pds.setMaxPoolSize(3);
//🍑 PoolDataSource객체로 Connection객체 반환받기
//PoolDataSource.getConnection() : PoolDataSource 객체에 저장된 Connection 객체 중 하나를 반환하는 메소드
Connection con1 = pds.getConnection();
System.out.println("con1 = "+ con1); //con1 = oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1ConnectionProxy$2oracle$1jdbc$1internal$1OracleConnection$$$Proxy@503f91c3
//PoolDataSource.getAvailableConnectionsCount() : PoolDataSource 객체가 제공 가능한 Connection 객체의 갯수를 반환하는 메소드
System.out.println("사용 가능한 Connection 객체의 갯수 = "+ pds.getAvailableConnectionsCount()); //사용 가능한 Connection 객체의 갯수 = 1
//PoolDataSource.close() : 사용한 Connection 객체를 제거하여 PoolDataSource 객체로 반환하는 메소드
con1.close();
System.out.println("사용 가능한 Connection 객체의 갯수 = "+ pds.getAvailableConnectionsCount()); //사용 가능한 Connection 객체의 갯수 = 2
//🍑 하나의 Connection객체만 "사용하고 반납" 반복
Connection con2 = pds.getConnection();
System.out.println("con2 = "+ con2); //con2 = oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1ConnectionProxy$2oracle$1jdbc$1internal$1OracleConnection$$$Proxy@503f91c3
con2.close();
Connection con3 = pds.getConnection();
System.out.println("con3 = "+ con3); //con3 = oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1ConnectionProxy$2oracle$1jdbc$1internal$1OracleConnection$$$Proxy@503f91c3
con3.close();
Connection con4 = pds.getConnection();
System.out.println("con4 = "+ con4); //con4 = oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1ConnectionProxy$2oracle$1jdbc$1internal$1OracleConnection$$$Proxy@503f91c3
con4.close();
}
}
반응형
'jdbc' 카테고리의 다른 글
[jdbc] 6. 학생관리 프로그램 (0) | 2024.05.14 |
---|---|
[jdbc] 4. JDBC 프로그램의 활용 (0) | 2024.05.13 |
[jdbc] 3. CRUD기능을 구현하는 JDBC 프로그램 작성법 (0) | 2024.05.13 |
[jdbc] 2. (java.lang패키지) Class객체(클래즈) (0) | 2024.05.12 |
[jdbc] 1. JDBC 프로그램 작성을 위한 환경설정 (0) | 2024.05.12 |