PreparedStatement를 이용해서 지정된 sql문에 사용자로부터 컬럼명과 컬럼값을 입력 받아서 해당 sql문을 조회한 결과를 출력하는 메소드를 작성하던 도중 예외 발생도 없는데 계속해서 결과값이 안 나오는 상황이 생겼다.
보통은 sql문에 문제가 있어서 오류가 나는 경우 java.sql.sqlsyntaxerrorexception: ora-00911: 문자가 부적합합니다. 라는 메시지가 뜨는데 해당 메시지는 뜨지도 않고 결과값도 조회가 안 돼서 뭐가 문젠가 했더니... 위치홀더에 값 대입을 잘못해주고 있었다.
//view 클래스의 사용자로부터 검색할 데이터를 받는 메소드
public int selectSubMenu() {
int choice=0;
while(true) {
System.out.println("==========조회할 항목 선택============");
System.out.println("1. 부서");
System.out.println("2. 직책");
System.out.println("3. 이름");
System.out.println("4. 급여 오름차순");
System.out.println("5. 급여 내림차순");
System.out.print("번호 선택 : ");
choice=sc.nextInt();
switch(choice) {
case 1,2,3,4,5 : return choice;
default : System.out.println("번호를 다시 선택하세요.");
}
}
}
//selectSubMenu에서 1~3번을 선택했을 때 검색할 데이터 입력
public String selectData() {
sc.nextLine();
System.out.println("검색할 내용 입력 : ");
String data=sc.nextLine();
return data;
}
------------------------------------------------------------------------------
//dao 클래스의 사용자가 원하는 데이터 조회 메소드
public List<Employee> selectEmployee(Connection conn, int choice, String data) {
PreparedStatement pstmt=null;
ResultSet rs=null;
List<Employee> employees=new ArrayList();
String sql=this.sql.getProperty("selectWhereEmp");
//sql문은 "select * from employee where ? like ?"인 상태
try {
//급여 오름차순, 내림차순 선택한 경우 다른 sql문으로 다시 셋팅
if(choice==4) {
sql=this.sql.getProperty("salaryAsc");
}else if(choice==5) {
sql=this.sql.getProperty("salaryDes");
}
switch(choice) {
case 1 : pstmt.setString(1,"dept_title"); break;
case 2 : pstmt.setString(1,"job_code"); break;
case 3 : pstmt.setString(1,"emp_name"); break;
}
pstmt.setString(2,"%"+data+"%");
pstmt=conn.prepareStatement(sql);
rs=pstmt.executeQuery();
while(rs.next()) {
employees.add(getEmployee(rs));
}
}catch(SQLException e) {
e.printStackTrace();
}finally {
JDBCTemplate.close(rs);
JDBCTemplate.close(pstmt);
}
return employees;
}
다른 곳에서 에러난 게 아닌 걸 보여주려고 끌어온 코드가 길어졌지만 결국 문제는 switch문에서 일어났다.
PreparedStatement는 위치홀더가 존재하는 sql문을 먼저 넣고 시작하기 때문에 set자료형 메소드로 해당 자리 인덱스에 원하는 값을 대입해줄 수 있는데(이전 게시글 참고) 이때 자동으로 set자료형에 맞게 sql문에서도 자료형을 맞춰준다!
그렇기 때문에 컬럼명을 대입하는 경우 set자료형 메소드를 사용하면 dept_title이라는 컬럼이 sql문 안에서 ‘dept_title’ 상태로 들어가기 때문에 해당 컬럼을 찾지 못해서 데이터를 불러오지 못했다.
변수 data를 넣을 때는 자료형 맞춰주는 걸 생각해서 “%”+data+”%” 상태로 넣어줘놓고… 컬럼명은 머릿속에서 문자로 생각하고 있었다.
위 switch문 안에 코드를 pstmt.setString();
대신 sql문 자체를 "select * from employee where #1 like ?"
로 적어놓고 replace 메소드를 이용해서 sql=sql.replaceAll("#1","dept_title");
로 작성해주면 sql문 자체가 “select * from employee where dept_title like ?” 상태로 바뀐다.
data는 문자열 형식으로 넣는 게 맞기 때문에 setString() 메소드를 그대로 사용해도 된다.
그리고 보통 sql문 예외가 발생하는 경우에는 보통 습관적으로 세미콜론(;)를 포함한 경우가 많으므로 java에서 작성한 sql문에는 형식을 맞춰서 작성하되, 세미콜론을 함께 작성하지 않도록 주의한다.