위치홀더 사용 시 주의할 점

EUNJI LEE·2023년 4월 24일
0

JDBC

목록 보기
3/5
post-custom-banner

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문에는 형식을 맞춰서 작성하되, 세미콜론을 함께 작성하지 않도록 주의한다.

profile
천천히 기록해보는 비비로그
post-custom-banner

0개의 댓글