1) 개념
Driver 등록
//오라클 드라이버 클래스 경로
Class.forName("oracle.jdbc.driver.OracleDriver");
//try-catch 구문 필요
//드라이버 클래스명에 오타가 있거나 라이브러리가 추가 되지 않았을 경우 해당 클래스를 찾지 못했다는 exception 발생 가능
Connection 생성
1-1. properties를 이용하지 않는 방법
Connection 변수명
= DriverManager.getConnection("jdbc:oracle:thin:@ip주소:포트번호:버전정보","user","password");
1-2. properties를 사용하는 방법
Properties prop = new Properties();
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, prop);
Statement 생성
Class.forName(driver);
Connection conn = DriverManager.getConnection(url,user,password);
Statement stmt = conn.createStatement();
ResultSet rset = smtm.executeQuery("SELECT EMP_ID, EMP_NAME FROM EMPLOYEE");
Result set 형태의 결과문 출력
while(rset.next()){
System.out.println(rset.getString("EMP_ID") + rset.getString("EMP_NAME");
결과 값 반환 후 close를 통해 사용한 자원 닫아주기
try{}
catch{}
finally{
try{
if(conn != null && !conn.isClosed())
rset.close()
}catch{}
- 드라이버 등록
- properties 생성
- Class.forName을 통해 드라이브 등록
- Connection C이름 ManagerDriver.getConnection()을 통해 연결
- Statement 생성(Statement S이름 = C이름.createStatement();)
- S이름.executeQuery("SQL 실행 구문") 을 통해 SQL 질의 수행
- 결과문 출력(while(rset.next()))
DTO 생성
모든 내용을 조회하는 경우 결과를 ArrayList에 담아서 저장
EmployeeDTO = null;
Connection conn = getConnection();
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
empList = new ArrayList<>();
while(rset.next()) {
row = new EmployeeDTO();
row.setEmpID(rset.getString("EMP_ID"));
row.setEmpName(rset.getString("EMP_NAME"));
row.setEmpNo(rset.getString("EMP_NO"));
row.setEmail(rset.getString("EMAIL"));
row.setPhone(rset.getString("PHONE"));
row.setDeptCode(rset.getString("DEPT_CODE"));
row.setJobCode(rset.getString("JOB_CODE"));
row.setSalary(rset.getInt("SALARY"));
row.setBonus(rset.getDouble("BONUS"));
row.setManagerId(rset.getString("MANAGER_ID"));
row.setHireDate(rset.getDate("HIRE_DATE"));
row.setEntDate(rset.getDate("ENT_DATE"));
row.setEntYn(rset.getString("ENT_YN"));
empList.add(row);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(conn);
close(stmt);
close(rset);
}
for(EmployeeDTO arr : empList) {
System.out.println(arr);
}
1) PreparedStatement
Class.forName(driver);
Connection conn = DriverManager(driver,user,password);
PreparedStatement pstmt = null;
ResultSet rset = null;
pstmt = conn.preparedStatement(SQL구문);
2) ? 위치홀더
Class.forName(driver);
Connection conn = DriverManager(url, user, password);
PreparedStatement pstmt = null;
ResultSet rset = null;
String query = "SELECT * FROM EMPLOYEE WHERE EMP_ID = ? AND EMP_NAME = ?"
pstmt = conn.preparedStatment(query);
// 위치 홀더에 값 전달
// 해당 상황에서는 2개이므로 1, 2로 표기한다
pstmt.setString(인덱스(1), 전달할 값);
pstmt.setStriing(인덱스(2), 전달할 값);
//실행문에서는 메소드에 아무것도 전달하지 않는다.
rset = pstmt.executeQuery();
String query = "SELECT * FROM EMPLOYEE WHERE EMP_NAME LIKE ? || '%' ";
3) 쿼리문 작성
Properties prop = new Properties();
prop.setProperty("keyString", "valueString");
try {
//new FileOutputStream("파일 경로" , "코멘트")
prop.storeToXML(new FileOutputStream("src/com/greedy/section02/preparedstatement/employee-query.xml"), "");
} catch (IOException e) {
e.printStackTrace();
}
document type definition : dtd (파일 타입 정의)
XML 작성
entry key : 구분할 수 있는 이름(String)
valueString : 쿼리문 내용
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<!-- 성으로 직원 조회하는 쿼리 -->
<entry key="selectEmpByFamilyName">
SELECT
E.*
FROM EMPLOYEE E
WHERE E.EMP_NAME LIKE ? || '%'
</entry>
</properties>
실행할 경우
Properties prop = new Properties();
prop.loadFromXML(new FileInputStream("경로"));
String query = prop.getProperty("설정한 키 이름");
pstmt = conn.preparedStatement(query);
pstmt.setString(인덱스, 변수)
rset = pstmt.executeQuery();
4) 장점
SQL injection을 막아줄 수 있음
1) Statement
변수를 입력받아 쿼리문을 전달하는 방식의 경우 변수에 SQL 구문을 넣어 올바른 값을 넣지 않아도 수행된 쿼리문의 조회값을 받아오도록 동작한다.
private static String empId = "200";
private static String empName = "' OR 1=1 AND EMP_ID = '200";
String query = "SELECT * FROM EMPLOYEE WHERE EMP_ID = '" + empId + "' AND EMP_NAME = '" + empName + "'";
try {
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
if(rset.next()) {
System.out.println(rset.getString("EMP_NAME") + "님 환영합니다.");
}else {
System.out.println("회원 정보가 없습니다.");
}
2) PreparedStatement
미완성된 쿼리를 작성하고, 쿼리를 완성하면서 올바른 정보 전달
위치 홀더에 올바르지 않은 값이 전달되면서, SELECT 절에서 일치하는 행을 찾을 수 없으므로 동작이 수행되지 않는다.
private static String empId = "200";
private static String empName = "' OR 1=1 AND EMP_ID = '200";
String query = "SELECT * FROM EMPLOYEE WHERE EMP_ID = ? AND EMP_NAME = ?";
try {
pstmt = conn.prepareStatement(query);
//미완성된 쿼리를 완성하면서 정보를 전달.
pstmt.setString(1, empId);
pstmt.setString(2, empName);
rset = pstmt.executeQuery();
if(rset.next()) {
System.out.println(rset.getString("EMP_NAME") + "님 환영합니다.");
}else {
System.out.println("회원 정보가 없습니다.");
}