JDBC의 개념
JDBC 순서
JDBC API
PreparedStatement
JDBC 활용
- JDBC(Java Database Connectivity)
- 개념: 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API
- JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.
- JDBC를 사용하는 이유
- 데이터를 파일이 아닌 Database에 저장하고 불러오기 위함
- 데이터의 처리를 Database에서 하는게 아닌 Java의 클래스와 메소드로 처리하기 위함
- 데이터의 처리를 DB에서 할 것 인지, Java에서 할 것 인지는 개발자의 선택이다.
- 만약 Java에서 처리하고자 한다면 Database에서 모든 데이터를 문자열 데이터로 형변환 한 후 가져오는 것이 편하다.
- JDBC에서 SELECT, DML 주의점
- SELECT는 PreparedStatement/Statement **executeQuery()**를 사용
- 1 ~ 7단계 진행
- DML은 PreparedStatement/Statement **executeUpdate()**를 사용
- 6단계 생략
- SELECT는 PreparedStatement/Statement **executeQuery()**를 사용
-
JDBC를 사용하기 위해서는 다음과 같이 선언해야한다.
-
순서
-
0단계: ojdbc8.jar를 클래스 패스에 추가한다.
- 오라클에서 다운받거나 오라클 DB 폴더의 jdbc\lib에서 찾는다.
-
1단계: import java.sql.*
-
2단계: oracle driver Loading한다.
-
Class.forName() 사용
-
Class.forName(Driver)
를 사용하여 DB 드라이버를 로드한다.-Class.forName()이란 Class.forName()이란 Java Reflection API의 일부이다. 자바 리플렉션 API는 구체적인 클래스의 타입을 알지 못해도 클래스의 변수 및 메소드 등에 접급하게 해주는 API이다. forName()은 Class 클래스에 속해있는데 Class 클래스는 JVM에서 동작할 클래스의 정보를 묘사하는 메타 클래스이다. 즉 클래스의 정보를 얻어오는 클래스이다. IN APIDOC: Returns the Class object associated with the class orinterface with the given string name. Invoking this method isequivalent to forName()은 파라메터로 들어간 클래스의 객체를 반환한다.
-
JDBC로 오라클 DB 드라이브를 등록하려면 다음과 같이 작성하면 된다.
Class.forName("oracle.jdbc.driver.OracleDriver");
-
Class.forName("oracle.jdbc.driver.OracleDriver")
만 입력하면 자동으로 객체가 생성되고 DriverManager에 등록된다. -
JDBC API 4.0 이상 부터는 JDBC 드라이브를 자동으로 로드하도록 DriverManager.getConnection 메서드가 개선되었다.
-
-
DriverManager.registerDriver(Driver arg0)를 사용
- Driver arg0: 드라이버 객체
- 오라클: new OracleDriver()
- Driver arg0: 드라이버 객체
-
-
3단계: Database에 connection
DriverManager.getConnection("url",계정 이름, 계정 비밀번호)
를 Connection 타입 변수에 저장- url은 jdbc:oracle:thin:@localhost:1521:orcl과 같은 것을 말함
- jdbc:벤더:클라이언트 유형:내 머신 이름: 포트번호: 오라클 버전
- url은 jdbc:oracle:thin:@localhost:1521:orcl과 같은 것을 말함
-
4단계: 문장객체(Statement) 생성한다.
- Statement 또는 PreparedStatement
- PreparedStatement는 SQL문을 캐시를 이용하여 저장한다. 즉 Statement는 컴파일 할 때 마다 SQL문을 실행하지만 PreparedStatement는 재활용이 가능하다. 성능상의 우위가 존재
- Statement: Connection 타입 변수.createStatement();를 이용
- Scrollable ResultSet: .createStatement(int resultSetType, int resultSetConcurrency)를 이용
- PreparedStatement: Connection 타입 변수.preparedStatement();를 이용
-
5단계: QL 문장을 실행한다.
- SELECT문의 경우: executeQurey()
- Statement executeQurey(sql);
- PreparedStatement executeQurey(); 파라미터에 sql문을 넣지 않는다.
- DML: executeUpdate()
- Statement executeUpdate(sql);
- PreparedStatement executeUpdate(); 파라미터에 sql문을 넣지 않는다.
- SELECT문의 경우: executeQurey()
-
6단계: SELECT문일 경우에만 ResultSet이라는 가상테이블을 처리한다.
- 데이터를 실제로 처리하는 단계
-
7단계: ResultSet, Statement, Connection 모두 close한다.
- 연 순서 반대로 닫는다. 즉 ResultSet -> Statement -> Connection
-
-
예
import java.sql.*;//1. import public class DB { public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //Class.forName("oracle.jdbc.driver.OracleDriver"); //2. 드라이버 로드 conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");//3.Connnection stmt = conn.createStatement();//4. statement 생성 //5.Select문의 경우 Statement의 executeQurey()로 쿼리문을 시행 String sql = " SELECT empno, ename, (sal * 1.1) AS \"보너스\" " + " FROM emp "; //실제 쿼리문을 작성: 쿼리문의 ;는 생략 rs = stmt.executeQuery(sql); //실행한 쿼리문의 결과를 ResultSet에 저장 //ResultSet은 일종의 가상 테이블이다. //6. ResultSetd이라는 가상의 테이블을 처리한다. //ResultSet next()를 사용한다. next()는 하나의 레코드를 처리한다. //만약 결과가 단 하나의 행이라면 단순히 rs.next()를 사용한다. //하지만 결과가 여러행이라면 while문으로 처리한다. while(rs.next()) {//rs.next()가 참 일 동안 == 다음 레코드가 없는동안 루프 int empno = rs.getInt("empno"); String ename = rs.getString(2); double bonus = rs.getDouble("보너스"); System.out.println(empno + " , " + ename + " , " + bonus ); } } catch (SQLException e) { System.out.println("Connection Failure"); } //7.close try { //연 순서의 반대로 닫는다. if(rs != null) rs.close(); //ResultSet 인스턴스가 생성되지 않았다면 이 과정은 진행되지 않아야 한다. if(stmt != null) stmt.close(); if(conn != null) conn.close(); }catch(SQLException e){ } } }
-
rs.getString(int columnIndex) , rs.getDouble(int columnIndex), rs.getInt(int columnIndex)
- ResultSet에 저장된 데이터를 java로 추출할 때 사용하는 메소드
- 파라메터에는 오라클 컬럼 인덱스(1부터 시작)이나 컬럼 이름을 사용해서 해당하는 컬럼의 값을 추출한다.
sal * 1.1
처럼 컬럼의 이름이 특정 이름을 가지고 있지 않을 경우 컬럼 인덱스를 넣거나 별창을 사용할 수 있다.
-
PreparedStatement
-
PreparedStatement와 Statement의 차이
- 일반적인 SQL Engine의 과정은 다음과 같다.
- Syntax Check
SELECT job FROM emp;
에서 틀린 문장이 있는가?
- Object Check
SELECT job FROM emp;
에서 emp가 실제로 존재하는가? job 컬럼이 실제로 존재하는가?
- Run
- Syntax Check
- Statementsms는 위 3단계를 모두 수행한다.
- PreparedStatement는 처음 한 번만 세 단계를 거친 후 캐시에 담아 재사용을 한다.
- 만약 동일한 쿼리를 반복적으로 사용한다면 PreparedStatement가 DB에 훨씬 적은 부하를 주며, 성능도 더 좋다.
- Statement는 중간에 변수를 사용해야 할 경우 SQL문법처럼 ' '로 둘러쌓여야 한다.
- 즉
String sql = "SELECT * FROM emp WHERE ename '" + this.name + "'" ;
- 즉
- 하지만 PreparedStatement는 ?를 사용하므로 그럴필요가 없다.
- 즉
String sql = "SELECT * FROM emp WHERE ename = UPPER(?);
- 이를 불완전 SQL이라고 하며
PreparedStatement setInt(int p, String x)
같은 것으로 완전 SQL문을 만들어야 한다.
- 이를 불완전 SQL이라고 하며
- 즉
- 일반적인 SQL Engine의 과정은 다음과 같다.
-
PreparedStatement와 Statement의 선언 차이
-
Statement
String sql = "SELECT empno, dname" + "FROM emp INNER JOIN dept ON emp.deptno = dept.deptno" + "WHERE ename = '" + name + "'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); //Statement는 executeQuery(sql)에 SQL문을 파라메터로 전달
- Statement는 executeQuery(sql)가 실행될 때 SQL문을 전달한다. 이때 SQL문은 반드시 완성된 상태여야 한다.
- Statement는 SQL문을 수행하는 과정에서 매 번 컴파일을 하므로 성능상의 문제가 존재한다.
-
PreparedStatement
String sql = " SELECT deptno, dname, loc " + " FROM dept" + " WHERE deptno = ? OR dname = UPPER(?)"; //불완전 SQL문 PreparedStatement pstmt = conn.prepareStatement(sql); //PreparedStatement가 SQL문을 입력하는 순간 //PreparedStatement는 불완전 SQL문을 완전한 SQL문으로 만들어야 한다. System.out.println("검색할 부서의 번호"); int deptno = sc.nextInt(); pstmt.setInt(1, deptno); System.out.println("검색할 부서의 이름"); String dname = sc.next(); pstmt.setString(2, dname); . . . ResultSet rs = pstmt.executeQuery();//PreparedStatement는 executeQuery()를 빈칸으로 둔다.
- PreparedStatement는 Statement에 비해 성능성의 이점이 있다.
?
이 포함된 SQL문은 불완전 SQL문이다. 이 문장도 쿼리 문장 분석 -> 객체 체크을 한다.- PreparedStatement는
?
부분에만 계속 변환을 주어 지속적으로 SQL문을 수행할 수 있다.
-
-
주의점: PreparedStatement의 ?는 Sql문 전체를 받을 수 없다. - 불완전 Sql문 자체도 문법검사, 객체검사를 진행하기 때문이다.
-
PreparedStatement의 선언 순서
- 불완전 SQL문 작성
?
을 포함한 문장을 말한다.
- Connection prepareStatement(sql)로 prepareStatement 인스턴스 생성
- 완전 SQL문을 작성: set~~~을 이용
- pstmt.setInt(int parameterIndex, String x)
- int parameterIndex: 불완전 SQL문의
?
인덱스 --> 1부터 시작
- int parameterIndex: 불완전 SQL문의
- pstmt.setString(int parameterIndex, String x)
- 그 외 등등...
- pstmt.setInt(int parameterIndex, String x)
- ResultSet 인스턴스 생성
ResultSet rs = pstmt.executeQuery()
- 주의점: PreparedStatement는 executeQuery() 파라메터에 인자를 넣지 않는다.
- 이후 과정은 동일
-
PreparedStatement 예
package Run; import java.util.Scanner; import java.sql.*; import co.example.libs.*; public class asd { public static void main(String[] args) throws SQLException { Scanner sc = new Scanner(System.in); //2,3 DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnetion(); //4. PreparedStatement String sql = " SELECT deptno, dname, loc " + " FROM dept" + " WHERE deptno = ? OR dname = UPPER(?)"; //불완전 SQL문 PreparedStatement pstmt = conn.prepareStatement(sql); //PreparedStatement가 SQL문을 입력하는 순간 //PreparedStatement는 불완전 SQL문을 완전한 SQL문으로 만들어야 한다. System.out.println("검색할 부서의 번호"); int deptno = sc.nextInt(); pstmt.setInt(1, deptno); System.out.println("검색할 부서의 이름"); String dname = sc.next(); pstmt.setString(2, dname); //5 ResultSet rs = pstmt.executeQuery();//PreparedStatement는 executeQuery()를 빈칸으로 둔다. //6. // if(flag) { while(rs.next()) { String deptno1 = rs.getString(1); String two = rs.getString(2); String loc = rs.getString(3); System.out.println(deptno1 + "\t" + two + "\t" + loc); //} //} else { // System.out.println("대상이 없습니다."); } //7. DBClose.close(conn, pstmt, rs); } }
-
-
4 Scrollable ResultSet
-
Scrollable Statement
- 기존의 Statement는 Forward Only만을 제공했다.
- 따라서 기존의 Statement는 한 레코드를 읽고 다음 테이블만 계속해서 읽을 수 있었다.
- 하지만 Scrollable Statement는 전후 이동이 가능하다.
- 따라서 Scrollable ResultSet는 한 레코드를 읽고 내가 원하는 레코드로 이동시킬 수 있다.
- 따라서 Scrollable ResultSet는 양방향 스크롤 기능이 추가되었다.
- 기존의 Statement는 Forward Only만을 제공했다.
-
Scrollable ResultSet의 선언
-
4단계: 문장객체(Statement) 생성한다.
에서Statement createStatement(int resultSetType, int resultSetConcurrency)
를 이용한다. -
예
DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnection(); //2,3 Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); //4. Scrollable ResultSet을 사용한다.
-
Scrollable ResultSet 생성자 파라미터
- int resultSetType
- ResultSet.TYPE_FORWARD_ONLY: Foward Only, 오직 next()만 가능하다.
- ResultSet.TYPE_SCROLL_INSENSITIVE: 불감, 스크롤은 가능하나 변경된 사항은 적용되지 않는다.
- 최초 Result Set이 생성된 시점의 데이터 만 볼 수 있다.
- ResultSet.TYPE_SCROLL_SENSITIVE: 민감, 스크롤은 가능하나 변경된 사항은 적용된다.
- Database에 적용된 변경 사항이 바로 적용되어 새로운 데이터를 볼 수 있다,
- 위 3개 인자는 전부 연결을 닫고 다시 열면 변경 내역이 표시된다.
- int resultSetConcurrency
- ResultSet.CONCUR_READ_ONLY: 수정 불가능, 읽기 전용
- ResultSet.CONCUR_UPDATABLE: 수정 가능
- int resultSetType
-
Scrollable ResultSet Method
-
Method
메소드 설명 boolean absolute(int row) row값에 해당하는 절대 위치로 이동, 음수면 마지막 레코드에서 음수만큼 뒤로 이동 boolean relative(int rows) 현재 위치를 기준으로 row만큼 앞/뒤로 이동 boolean next() 다음 레코드로 이동 boolean previous() 이전 레코드로 이동 void afterLast() 마지막 행 다음 레코드로 이동: 행이 없으므로 행을 이동하지 않으면 마지막행 다음의 결과 집합
이라는 오류가 발생void beforeFirst() 처음 레코드 전으로 커서 이동: 행이 없으므로 행을 이동하지 않으면 마지막행 다음의 결과 집합
이라는 오류가 발생int getType() int resultSetType의 타입을 int로 반환: TYPE_FORWARD_ONLY 1003/TYPE_SCROLL_INSENSITIVE 1004/TYPE_SCROLL_SENSITIVE 1005 int getConcurrency() int resultSetConcurrency의 타입을 int로 반환: ResultSet.CONCUR_READ_ONLY 1007/ResultSet.CONCUR_UPDATABLE 1008 boolean isFirst() 커서가 테이블의 첫번째 레코드가 있는지 boolean으로 반환 boolean isLast() 커서가 테이블의 마지막 레코드에 있는 지 boolean으로 반환 -
예
public class test { public static void main(String[] args) throws SQLException { DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnection(); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, ename, job, sal FROM emp_Copy"); rs.absolute(8); //테이블 레코드의 절대 위치로 이동 boolean rs.absolute(-2);//테이블 마지막 레코드에서 음수만큼 뒤로 이동 boolean rs.first();//테이블 첫번째 레코드로 이동 boolean rs.last();//테이블 마지막 레코드로 이동 boolean System.out.println(rs.isFirst()); //커서가 테이블의 첫번째 레코드가 있는지 boolean으로 반환 System.out.println(rs.isLast()); //커서가 테이블의 마지막 레코드에 있는 지 boolean으로 반환 System.out.println(rs.getType()); //int resultSetType의 타입을 int로 반환 //TYPE_FORWARD_ONLY 1003 //TYPE_SCROLL_INSENSITIVE 1004 //TYPE_SCROLL_SENSITIVE 1005 System.out.println(rs.getConcurrency()); //ResultSet.CONCUR_READ_ONLY 1007 //ResultSet.CONCUR_UPDATABLE 1008 rs.beforeFirst();// 처음 레코드 전으로 커서 이동 rs.afterLast();// 마지막 레코드 다음으로 커서 이동 마지막행 다음의 결과 집합 rs.relative(-1);//현재 레코드 위치에서 앞/뒤로 이동 rs.next(); rs.previous(); System.out.println(rs.getInt(1) + rs.getString(2) + rs.getString(3) + rs.getDouble(4)); DBClose.close(conn); } }
-
-
Scrollable ResultSet Updatable
-
Scrollable ResultSet의 가장 큰 장점은 INSEET, DELETE, UPDATE가 가능하다는 것이다.
-
Scrollable ResultSet로 테이블 데이터를 삽입, 수정, 삭제하려면
ResultSet.CONCUR_UPDATABLE
이어야 한다. -
INSERT
-
METHOD
- moveToInsertRow(): 현재 커서 위치는 커서가 삽입 행에 있는동안 저장된다. 삽입 행은 업데이트할 수 있는 ResultSet과 연결된 특수한 행으로 기본적으로 ResultSet에 행을 추가하기 전에 Updater 메소드를 호출하여 새 행을 생성할 수 있다.
- insertRow(): insertRow()는 테이블에 행을 추가한다. insertRow()가 실행되기 위해서는 삽입행에 위치해야 한다.
- UpdateInt/Strint/Double/CharacterStream/Object(int columnIndex, Type(String, int ...) X)
- 해당하는 데이터를 ResultSet에 업데이트한다.
- int columnIndex: SELECT문으로 선택한 컬럼의 순서, 또는 이름
- 예:
"SELECT empno, ename, job, sal FROM emp_Copy"
이라면- rs.updateInt(1, 8888);은 empno에 8888을 삽입
- rs.updateString(2, "한지민");는 ename에 한지민을 삽입
- 예:
-
INSERT 순서
public class test { public static void main(String[] args) throws SQLException { DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnection(); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, ename, job, sal FROM emp_Copy"); rs.moveToInsertRow(); //1. rs.updateInt(1, 8888); //2. 열에 값 삽입 rs.updateString(2, "한지민"); rs.updateString(3, "DERVELOP"); rs.insertRow(); //3. System.out.println(rs.getInt(1) + rs.getString(2) + rs.getString(3) + rs.getDouble(4)); DBClose.close(conn); } }
-
-
UPDATE
-
사용하는 메소드는 INSERT와 같다.
-
updateRow()로 DB에 반영
-
예
public class test { public static void main(String[] args) throws SQLException { DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnection(); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, ename, job, sal FROM emp_Copy"); rs.last(); rs.updateDouble("sal", 5000); rs.updateRow(); System.out.println(rs.getInt(1) + rs.getString(2) + rs.getString(3) + rs.getDouble(4)); DBClose.close(conn); } }
-
-
하지만 수정하려는 레코드의 위치로 이동해야 한다.
-
-
DELETE
-
deleteRow()
로 삭제 -
예
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class test { public static void main(String[] args) throws SQLException { DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnection(); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, ename, job, sal FROM emp_Copy"); rs.last(); rs.deleteRow(); rs.last(); System.out.println(rs.getInt(1) + rs.getString(2) + rs.getString(3) + rs.getDouble(4)); DBClose.close(conn); } }
-
-
-
-
Properties 파일을 활용하여 3단계 까지 필요한 인자를 재활용
-
3단계 까지 과정을 다른 클래스로 분리
-
dbinfo.properties
DBDRIVER=oracle.jdbc.driver.OracleDriver DBURL=jdbc:oracle:thin:@localhost:1521:orcl DBUSER=scott DBPASSWD=tiger
-
co.example.libs: DBConnection.java, DBClose.java, JDBC.java.java
package co.example.libs; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class DBConnection { private Properties p; DBConnection(){ //생성자 dbinfo.properties를 properties로 저장 p = new Properties(); File file = new File("./dbinfo.properties"); //this.p.load(new FileInputStream(file));로 dbinfo.properties에 저장한 정보를 불러온다. try { this.p.load(new FileInputStream(file)); } catch (FileNotFoundException e) { System.out.println("File Not Found"); } catch (IOException e) { System.out.println("Wrong Input"); } } public Connection getConnetion() { Connection conn = null; //2. 드라이버 로드: JDBC 4.0 부터는 필요 없음 try { Class.forName(this.p.getProperty("DBDRIVER")); //3. connection conn = DriverManager.getConnection(this.p.getProperty("DBURL"),this.p.getProperty("DBUSER"),this.p.getProperty("DBPASSWD")); } catch (ClassNotFoundException e) { System.out.println("Driver Not Found");
package co.example.libs; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBClose { public static void close(Connection conn) { try { if(conn != null)conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(Connection conn, Statement stmt) { if(conn != null) try { if(stmt != null) stmt.close(); if(conn != null) conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(Connection conn, Statement stmt, ResultSet rs) { if(conn != null) try { if(rs != null) rs.close(); if(stmt != null) stmt.close(); if(conn != null) conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package co.example.libs; //1 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.Date; import java.util.Scanner; public class JDBC { private Scanner sc; public JDBC(){ sc = new Scanner(System.in); } public void runJDBC() { //2,3 DBConnection dbconn = new DBConnection(); Connection conn = dbconn.getConnetion(); //4 pstmt JDBC jdbc = new JDBC(); String sql = jdbc.enterSql(); Statement stmt = jdbc.getStatement(conn); //5.executeQuery ResultSet rs = jdbc.executeQuery(stmt, sql); //6.ResultSet을 처리 jdbc.ExecuteResultSet(rs); //7. DBClose.close(conn, stmt, rs); } public String enterSql() { System.out.println("ENTER SQL: "); String query = ""; int i=1; while(true) { System.out.print(i + ": "); query = query + " " + sc.nextLine(); i++; if(query.charAt(query.length() -1) == ';') { query = query.substring(0, query.length()-1); break; } } System.out.println("Entered Query... " + query); return query; } public Statement getStatement(Connection conn){ Statement stmt = null; try { stmt = conn.createStatement(); } catch (SQLException e) { System.out.println("Syntax Error "); } return stmt; } public ResultSet executeQuery(Statement stmt, String sql) { ResultSet rs = null; try { rs = stmt.executeQuery(sql); System.out.println("SQL Injection Success"); } catch (SQLException e) { System.out.println("Yon Entered a Wrong SQL"); } return rs; } public void ExecuteResultSet(ResultSet rs) { ResultSetMetaData rsmd = null; String[] columnName = new String[20]; String[] columnType = new String[20]; try { rsmd = rs.getMetaData(); for(int i=1;i<=rsmd.getColumnCount();i++) { columnName[i-1] = rsmd.getColumnName(i); columnType[i-1] = rsmd.getColumnTypeName(i); } } catch (SQLException e) { System.out.println("Column name"); } try { int i=0; while(rs.next()) { while(columnType[i] == "NUMBER") { int one = rs.getInt(columnName[i]); System.out.print(one + ","); i++; } while(columnType[i] == "VARCHAR2") { String two = rs.getString(columnName[i]); System.out.print(two+ ","); i++; } while(columnType[i] == "DATE") { Date d = rs.getDate(columnName[i]); System.out.print(","+ d); i++; } System.out.println(); i = 0; } } catch (SQLException e) { System.out.println("Cannot find Column name"); } }
}
-
Run: main.java
package Run; import co.example.libs.*; public class main { public static void main(String[] args) { JDBC j = new JDBC(); j.runJDBC();
} }
-