DAY-30. Jdbc Dbcp, 커넥션 풀 이용

3 minute read

🔐 2022-04-13

데이터베이스 - JDBC

❗ 수업을 듣고, 개인이 공부한 내용을 적은 것 이기에 오류가 많을 수도 있음

🔔 DBCP이용

logging,pool,dbcp 라이브러리(apache) 사용

기존 코드

private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String username = "kh";
private String password = "kh";

// 예외 전달하기
public int insert(CafeDTO dto) throws Exception {

	// 쿼리문안에 삽입할 문자들을 ?로 해두고 나중에 setString을 이용해 설정
	String sql = "insert into cafe values (seq_cafe.nextval,?,?, sysdate)";

	try(Connection con = DriverManager.getConnection(url,username,password);
		PreparedStatement pstmt = con.prepareStatement(sql);) {

		// ?에 해당하는 인자값 세팅 -> 컬럼의 자료형에 따라 세팅
		pstmt.setString(1, dto.getProduct_name()); // 쿼리문의 첫 번째 ?의 인자값 -> 1 -> 컬럼의 인덱스가 아님
		pstmt.setInt(2, dto.getPrice()); // 쿼리문의 두 번째 ?의 인자값 -> 2 -> 컬럼의 인덱스가 아님

		// 쿼리문을 실행
		int rs = pstmt.executeUpdate(); // 인자값을 sql로 넘겨주지 않는다
		return rs;
	}
}

DBCP, 커넥션 적용

//BasicDataSource 클래스 인스턴스 생성
  private BasicDataSource bds = new BasicDataSource();

// DBCP를 생성하기 위해 필요한 설정값 셋팅
// 생성자를 만들어 초기값 셋팅
public CafeDAO() {
	// CafeDAO 생성자가 호출되면 자동으로 bds에 초기 설정값 셋팅
	bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
	bds.setUsername("kh");
	bds.setPassword("kh");
	// 커넥션 개수 셋팅
	bds.setInitialSize(10);
}

// 커넥션 풀에 있는 커넥션을 꺼내서 반환해주는 메서드
public Connection getConnection() throws Exception{
	return bds.getConnection(); // 데이터베이스 연결
}

public int insert(CafeDTO dto) throws Exception{ // 예외전가
	String sql = "insert into cafe values(seq_cafe.nextval, ?, ?, sysdate)";

	try(Connection con = this.getConnection();
		PreparedStatement pstmt = con.prepareStatement(sql)){

		pstmt.setString(1, dto.getProduct_name());
		pstmt.setInt(2, dto.getPrice());

		int rs = pstmt.executeUpdate();
		return rs;
	}
}

  • 매번 Connection con = DriverManager.getConnection(url,username,password); 하기가 귀찮다 (모든 메서드 마다 해줘야 하기 때문에)
  • 그래서 객체를 필요할 때 마다 꺼내서 쓸수 있게 “Pool”을 생성하고 그 Pool에 객체를 담아준다 → 공구통에 공구 담아두고 필요한 도구를 찾아서 쓰는 느낌?
  • 라이브러리를 apache를 사용하고 있기 때문에 , BasicDataSource를 사용한다
  • 생성자를 만들어 해당 클래스가 호출 될 때 데이터 객체의 초기값 설정을 해두는 코드를 넣어둔다 (url , username, password, InitialSize) 셋팅
  • 사용하고 싶은 객체를 반환하는 메서드를 만든다. 여기선 데이터베이스와 연결 할 수 있는 getConnection 생성

Connection Pool

  • 간단히 정의하면,미리 커넥션 객체를 생성하고 해당 커넥션 객체를 관리하는 것을의미
  • 데이터베이스와 연결된 커넥션을 미리 만들어서 풀(pool)속에 저장해 두고 있다가 필요할 때 커넥션을 풀에서 쓰고 다시 풀에 반환하는 기법

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ssang8417&logNo=221858327113

DBCP(Database Connection Pool)

Connection Pool을 이용해서 지정한 개수만큼 Connection 객체를 생성 해놓고, 선착순으로 접속한 클라이언트한테 가지고 있는 connection 분배해주고 그 뒤로 들어오는 클라이언트들은 앞에 접속했던 클라이언트들이 connection을 반납할 때 까지 대기 → ex) 수강신청 , 식당 (웨이팅시)

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=jujinho218&logNo=220632451200

❗ 오류 : ORA-12519, TNS:no appropriate service handler found

cmd>sqlplus / as sysdba
sqlplus>alter system set processes=300 scope=spfile;
sqlplus>shut immediate;
sqlplus>startup

오라클 프로세스를 초과해서 발생하는 일

https://aricode.tistory.com/10

🔔 MemberServcie

참고자료 https://riucc.tistory.com/350

🔔 Singleton 싱글톤 적용

CafeDAO - 기존

//BasicDataSource 클래스 인스턴스 생성
private BasicDataSource bds = new BasicDataSource();

// DBCP를 생성하기 위해 필요한 설정값 셋팅
// 생성자를 만들어 초기값 셋팅
public CafeDAO() {
	// CafeDAO 생성자가 호출되면 자동으로 bds에 초기 설정값 셋팅
	bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
	bds.setUsername("kh");
	bds.setPassword("kh");
	// 커넥션 개수 셋팅
	bds.setInitialSize(10);
}

// 커넥션 풀에 있는 커넥션을 꺼내서 반환해주는 메서드
public Connection getConnection() throws Exception{
	return bds.getConnection(); // 데이터베이스 연결
}

Run 기존

CafeDAO dao = new CafeDAO();

CafeDAO - 싱글톤 적용

//BasicDataSource 클래스 인스턴스 생성
private BasicDataSource bds = new BasicDataSource();
private static CafeDAO instance = null; // 커넥션 풀을 하나만 만들어서 그 하나로만 사용 가능하게

// DBCP를 생성하기 위해 필요한 설정값 셋팅
// 생성자를 만들어 초기값 셋팅
private CafeDAO() {  // 생성자 private 변환
	// CafeDAO 생성자가 호출되면 자동으로 bds에 초기 설정값 셋팅
	bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
	bds.setUsername("kh");
	bds.setPassword("kh");
	// 커넥션 개수 셋팅
	bds.setInitialSize(10);
}

// 커넥션 풀을 한번만 만들고 run에서 실행하면 new CafeDAO()가 메모리에 담기고 그 뒤로는 null이 아니기에
// if문 실행안하고 return instance 실행
public static CafeDAO getInstance() {  // CafeDAO 인스턴스를 내부적으로 new 하고 반환하는 메서드
	if(instance == null) { // CafeDAO 인스턴스가 만들어진 적이 없다면 NEW를 하겠다
						// == DBCP -> Connection Pool을 하나 만들겠다
		instance = new CafeDAO();
	}
	// 만일 CafeDAO 인스턴스가 이미 존재한다면 == 이미 만들어진 Connection pool이 존재
	// 그런 경우라면 이미 있는 커넥션 풀을 통해서 접속을 제공
	return instance;
}

// 커넥션 풀에 있는 커넥션을 꺼내서 반환해주는 메서드
public Connection getConnection() throws Exception{
	return bds.getConnection(); // 데이터베이스 연결
}

Run - 싱글톤 적용

// CafeDAO()의 생성자를 private으로 바꾼뒤 -> CafeDAO dao = new CafeDAO()는 사용불가
CafeDAO dao = CafeDAO.getInstance(); // instance가 null 이라면 즉 처음 실행했을때
//CafeDAO.getInstance의 return 값은 new CafeDAO()가 될 것이다.
// 그래서 코드는 CafeDAO dao = new CafeDAO() 와 같은 코드
  • 싱글톤 적용을 안하면 사용자가 CafeDAO 인스턴스를 활용 할 때 매번 같은 커넥션 풀을 사용하게 된다
  • 따라서 하나의 인스턴스로 여러 사용자가 사용하게 끔 사용하기 위해 싱글톤을 적용한다
  • 기존 CafeDAO()의 생성자의 접근범위를 private으로 한다
  • static 변수를 둔 private static CafeDAO instance = null; 생성
  • 가장 처음에 실행될 때 새로운 인스턴스를 생성할 수 있게 instance의 값을 new CafeDAO()로 해주는 조건문을 만들어주고 return 값으로 돌려준다, 만약 먼저 인스턴스가 메모리에 생성이 되있다라면 → instance의 값을 null로 반환하는 메서드 생성
  • CafeDAO dao = CafeDAO.getInstance(); 에서 CafeDAO.getInstance() 값이 처음 실행한다면 즉, 메모리에 처음 올라간다면 new CafeDAO() 가 되고, 이미 메모리에 올라가있으면, null 이된다

Categories:

Updated:

Leave a comment