개발 노트/에러 화풀이 기록

[Spring] java.sql.sqlexception 소켓에서 읽을 데이터가 없습니다 에러 / c3p0, commons dbcp2 커넥션풀 사용

hectick 2022. 9. 1. 11:28

프로그램을 돌리다가 마주한 소켓에서 읽을 데이터가 없습니다 에러

 

스프링, 이클립스, 오라클DB, c3p0을 이용해서 개인 프로젝트를 하는 중이다.

사용자의 지시로 디비에 접근하는 명령은 괜찮은데, 서버에서 스케줄링으로 디비에 접근하려고 하면 소켓에서 읽을 데이터가 없다고 나온다.

이거 고치려고 2분만 2분만 하면서 코딩하다가 12시에서 새벽 3시 반이 되었다.

근데 못고쳤다.

코드를 한줄 한줄 로그를 찍어서 테스트했다.

내 코드는 코드를 실행하면서 dao가 c3p0의 ComboPooledDataSource 커넥션풀에서 커넥션을 가져와서 DB에 연결한다.

커넥션풀을 통한 db 연결이 처음엔 잘 된걸 보면, 프로그램이 돌아가다가 중간에 이 연결이 끊기는 것 같다고 추측했다.

 

 

9월 1일 목요일

오늘 학교에 등교해서 밥먹기전에 한번 돌려봤는데 된다.

어이가 없네

두고보자.

 

 

9월 2일 금요일

다음날이다.

다시 돌려봤더니 안된다.

얼탱이 없네?

 

이날 밤, 나는 커넥션풀을 이용하기 위한 라이브러리로 c3p0을 버리고 commons-dbcp2를 이용하기로 하였다. 

자기 전까지 dbcp2를 어떻게 쓰는지 구글링을 했는데, 커넥션풀이란 무엇인지,  dbcp2 사용하기 위한 bean 등록은 어떻게 하는지는 금방 이해할 수 있었으나, bean에 등록한 것을 이용해서 어떻게 커넥션 풀을 활용하는 코드를 짜야하는 진 감을 잡기 힘들었다...ㅜㅜ 어느 글은 getConnection()으로 connection 객체를 얻어와 사용하고.. 어디는 또 그냥 dataSource를 사용하고.. 혼란스러웠다

얼른 영어를 공부해서 영어로도 구글링 맘껏 해야지... ^^

 

자기전까지 계속 구글링만 하다 잠들었다...

 

 

9월 3일 토요일

원래는 구글링하면 root-context.xml 설정파일에 직접 등록하는게 많이 나오길래, 나도 이렇게 하려고 했는데, 이클립스에서 자꾸 전구모양을 띄우기도하고 여러모로 거슬려서 방향을 바꿨다.

 

commons-dbcp2의 BasicDataSource를 이용하기 위해 DBCPDataSource.java 클래스를 만들어서 다음 코드를 추가하였다. 

https://sjh836.tistory.com/148에 나온 코드와, 내가 인프런 강의를 들으면서 c3p0에 사용했던 구조를 토대로 짠 코드이다.

 

(사용하기 전에 먼저 라이브러리 등록부터 반드시 해줘야 한다!

나는 https://mvnrepository.com/artifact/org.apache.commons 에서 라이브러리를 찾아 pom.xml에 등록하는 편이다.

이번같은 상황에는 검색창에 dbcp2를 검색하여 맞는 버전을 등록한다! 난 최신버전 사용했음...)

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DBCPDataSource {
    
    @Bean(destroyMethod = "close")
    public BasicDataSource dataSource() {
    	BasicDataSource dataSource = new BasicDataSource();
    	dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver"); //오라클 DB 사용
	dataSource.setUrl("{DB경로}");
	dataSource.setUsername("{유저이름}");
	dataSource.setPassword("{비밀번호}");
    	
    	dataSource.setMaxTotal(20);
    	dataSource.setMaxIdle(20);
    		
    	dataSource.setTestOnBorrow(true);
    	dataSource.setTestOnReturn(false);
    	dataSource.setMaxWaitMillis(3000);
    	dataSource.setValidationQuery("SELECT 1 FROM DUAL");
    		
    	dataSource.setTestWhileIdle(true);
    	dataSource.setTimeBetweenEvictionRunsMillis(150000);
    	dataSource.setNumTestsPerEvictionRun(4);
    	dataSource.setMinEvictableIdleTimeMillis(-1);
    		
    	dataSource.setPoolPreparedStatements(true);
    	dataSource.setMaxOpenPreparedStatements(20);
    	return dataSource;
    }
}

 

그리고 위에서 return되는 dataSource를 DAO에 생성자 주입하여 사용했다. 예를 들면 다음과 같다.

나는 DAO에서 Jdbc Template를 사용하니 참고!

@Repository
public class UserDao {
	private JdbcTemplate template;

	@Autowired
	public UserDao(BasicDataSource dataSource) {
		this.template = new JdbcTemplate(dataSource);
	}
}

 

역시나 이전에 c3p0을 이용했을 땐 내가 코드를 잘못 짰던건지, c3p0의 커넥션풀을 사용하는 과정에서 DB와의 연결이 자꾸 끊겼던게 맞는 것 같다.

톰캣에 서버를 올리고 처음 로그인할 때는 잘 되었는데, 3시간 정도 뒤에 다시 로그인 하려고 했더니 500 에러가 뜨는 상황이 발생하였다.

어쨌든 dbcp2를 사용한 코드도 다시 짰으니, 변경된 프로젝트를 새로 서버에 올리고 테스트 하여 잘 돌아간 것을 확인하고 이날밤은 꿀잠 잤다.

비슷한 구조로 코드를 짰는데 왜 c3p0는 여러 에러가 나고 dbcp2는 잘될까...

톰캣 서버에 올리는 것도 c3p0는 에러나서 험난했는데

dbcp2는 톰캣 서버의 jdk 버전과 ojdbc 드라이버 버전을 맞추는 것 말곤 아주 스무스 했다.

톰캣 서버에 jdk1.8 버전이 설치되어 있었는데, 오라클 db로 19c 버전을 쓰는 나는 원래쓰던 ojdbc10에서 ojdbc8로 버전을 변경했다!

 

 

9월 4일 일요일

서버에 올린 상태로 하루가 지났는데도 잘 돌아간다. 행-복

 

 

 

여담...

이번 프로젝트를 진행하면서 느끼는 점

에러를 해결하려고 구글링하면 스프링 부트랑 인텔리제이를 사용한 환경이 엄청 많이 나온다.

그냥 스프링이랑 이클립스를 쓰는 나는 조금 서럽다.

나는 그냥 스프링 부트를 쓰기전엔 스프링을 먼저 알아야 하지 않을까? 생각해서 스프링을 쓴 것이고

이클립스로 자바를 처음 배워서 첫 스프링 프로젝트도 이클립스로 한 것 뿐인데...

나도 프로젝트 끝나면 갈아타야지.....