1. DB 연결

 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class connection {

 public static void main(String[] args) {
    -- try 블럭 안에 넣으면 finally 구문에서 연결끊기가 실행 안됨.
	Connection conn = null; 
	try {
		-- JDBC Driver를 메모리로 로딩하고, DriverManager에 등록
		Class.forName("com.mysql.cj.jdbc.Driver");
		    
		-- 연결하기
		conn = DriverManager.getConnection(
		    	"jdbc:mysql://localhost:3306/sample",
		    	"(아이디)",
		    	"(비밀번호)"
		       );
		    		
		    System.out.println("연결 성공");
		    	    
	} catch (ClassNotFoundException e) {
			e.printStackTrace(); -- 예외 종류, 발생 이유, 어디서 발생했는지 추적한 내용까지 출력
	} catch (SQLException e) {
			e.printStackTrace();
	} finally {
		 if (conn != null) { -- null 이면 굳이 닫을 필요 없기 때문.
			try {
				/* 연결 끊기 (try 구문 안에 넣으면 예외 발생시 실행이 안되기 때문에 
                finally 구문에서 무조건 실행되도록 함.) */
				conn.close();
				System.out.println("연결 끊기");
			} catch (SQLException e) {}
		}
	}
 }
}
 

 


 

2.  INSERT

 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserInsert {

   public static void main(String[] args) {
	 Connection conn = null;
	 try {
		  Class.forName("com.mysql.cj.jdbc.Driver");
		    
		  conn = DriverManager.getConnection(
		    	 "jdbc:mysql://localhost:3306/sample",
		    	 "(아이디)",
		    	 "(비밀번호)"
		    	 );
		    		
		  System.out.println("연결 성공");
		    
		  -- 매개변수화된 SQL문 작성
		  String sql = "" + "INSERT INTO users (
                       userid, username, userpassword, userage, useremail) " +
		    		   "VALUES (?,?,?,?,?)"; // 매개변수에 들어갈 값을 물음표로 표현해준다.
		    		
		   -- PreparedStatement 얻기 및 값 지정
		   PreparedStatement pstmt = conn.prepareStatement(sql); 
		   -- 연결 객체를 통해 sql문을 실행해서 결과문을 받을 statement를 준비하고,
	       -- 구현객체가 리턴되어 PreparedStatement 인터페이스 변수에 대입된다. 
              (아직 실행된 상태는 아니다.)
		    
		   pstmt.setString(1,  "winter"); 
		   pstmt.setString(2, "한겨울");
		   pstmt.setString(3, "12345");
		   pstmt.setInt(4, 25);
		   pstmt.setString(5, "winter@mycompany.com");
		    
		   -- SQL문 실행
		   int rows = pstmt.executeUpdate(); -- DB에서 insert문을 실행하는 메소드
		   System.out.println("저장된 행 수: " + rows); -- DB에 반영된 행의 수를 뜻함.
		   -- 정상적으로 실행되었다면 1이 나옴.		
		    
		   -- PreparedStatement 닫기
		   pstmt.close();
		   
	} catch (ClassNotFoundException e) {
			e.printStackTrace();
	} catch (SQLException e) {
			e.printStackTrace();
	} finally {
		if (conn != null) { 
			try {
				-- 연결 끊기 
				conn.close();
				System.out.println("연결 끊기");
			} catch (SQLException e) {}
		}
	}

 } 
}
 

 


 

3. UPDATE

 

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

public class BoardUpdate {

	public static void main(String[] args) {
		Connection conn = null;
		try {
		    Class.forName("com.mysql.cj.jdbc.Driver");
		    
		    conn = DriverManager.getConnection(
		    		"jdbc:mysql://localhost:3306/sample",
		    		"(아이디)",
		    		"(비밀번호)"
		    		);
		    		
		    -- 매개변수화된 SQL문 작성
		    String sql = new StringBuilder() -- 문자열 연결 메서드
                   .append("UPDATE boards SET ")
                   .append("btitle=?, ")
                   .append("bcontent=?, ")
                   .append("bfilename=?, ")
                   .append("bfiledata=? ")
                   .append("WHERE bno=?")
                   .toString();
		    
		    -- PreparedStatement 얻기 및 저장
		    PreparedStatement pstmt = conn.prepareStatement(sql);
		
		    pstmt.setString(1, "눈사람");
		    pstmt.setString(2, "눈으로 만든 사람");
		    pstmt.setString(3, "snowman.jpg");
		    pstmt.setBlob(4, new FileInputStream("src/DBtest/photo2.jpg"));
		    pstmt.setInt(5, 3); // boards 테이블에 있는 게시물 번호(bno) 지정
		    
		    -- SQL문 실행
		    int rows = pstmt.executeUpdate();
		    System.out.println("수정된 행 수: " + rows);
		    
		    -- PreparedStatement 닫기
		    pstmt.close();
		    
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				try {
				-- 연결 끊기
				conn.close();
			} catch (SQLException e) {}
		}
	}
	}

}
 

 


 

4. DELETE

 

public class BoardDelete {

	public static void main(String[] args) {
		Connection conn = null;
		try {
		    Class.forName("com.mysql.cj.jdbc.Driver");
		    
		    conn = DriverManager.getConnection(
		    		"jdbc:mysql://localhost:3306/sample",
		    		"(아이디)",
		    		"(비밀번호)"
		    		);
		    		
		    -- 매개변수화된 SQL문 작성
		    String sql = "DELETE FROM boards WHERE btitle=?";
		    
		    -- PreparedStatement 얻기 및 저장
		    PreparedStatement pstmt = conn.prepareStatement(sql);
		    pstmt.setString(1, "눈사람");
		    
		    
		    -- SQL문 실행
		    int rows = pstmt.executeUpdate();
		    System.out.println("삭제된 행 수: " + rows);
		    
		    -- PreparedStatement 닫기
		    pstmt.close();
		    
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				try {
				-- 연결 끊기
				conn.close();
			} catch (SQLException e) {}
		}
	}
	}

}
 

 


 

5.  SELECT

 

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.mysql.cj.jdbc.Blob;

public class BoardSelect {

	public static void main(String[] args) {
        Connection conn = null;
		
		try {
			-- JDBC Driver 등록
		    Class.forName("com.mysql.cj.jdbc.Driver");
		    
		    -- DB 연결
		    conn = DriverManager.getConnection(
                     "jdbc:mysql://localhost:3306/sample", 
                     "(아이디)", 
                     "(비밀번호)");
		    
		    -- 매개변수화된 SQL문 작성
		    String sql = "SELECT bno, btitle,bcontent, bwriter, 
                          bdate, bfilename, bfiledata 
                          from boards where bwriter =?";
		    
		    -- PreparedStatement 얻기 및 값 지정
		    PreparedStatement pstmt = conn.prepareStatement(sql);
		    pstmt.setString(1,"winter");
		    
		    -- SQL문 실행 후, ResultSet을 통해 데이터 읽기.
		    ResultSet rs = pstmt.executeQuery();
		    List<Board> boards = new ArrayList<>();
		    while(rs.next()) {
		    	Board board = new Board(); -- board 테이블의 행을 저장할 객체를 만듦.
		    	board.setBno(rs.getInt("bno"));
		    	board.setBtitle(rs.getString("btitle"));
		    	board.setBcontent(rs.getString("bcontent"));
		    	board.setBwriter(rs.getString("bwriter"));
		    	board.setBdate(rs.getDate("bdate"));
		    	board.setBfilename(rs.getString("bfilename"));
		    	board.setBfileData(rs.getBlob("bfileData"));
		    	
		        System.out.println(board); -- 콘솔에 출력
		    }
		    rs.close();
		    
		    
		    pstmt.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) { 
				try {
					-- 연결 끊기 
					conn.close();
				} catch (SQLException e) {}
			}
		}
	}
}
 

 

 

 

 

 

 

[ 내용 참고 : 책 '이것이 자바다' ]

 

 


 

 

1.  JDBCJava DataBase Connectivity 

 

출처 :  https://www.geeksforgeeks.org /

 

 

출처 :   https://www.geeksforgeeks.org/
출처 : 책 '이것이 자바다'

 

 

 

👩🏻‍💻 자바 / JSP 프로그램 내에서 데이터베이스와 관련된 작업을 처리할 수 있도록 도와주는 자바 표준 인터페이스

👩🏻‍💻 관계형 데이터베이스 시스템에 접근하여 SQL 문을 실행하기 위한 자바 API 또는 자바 라이브러리

   ⚡️ JDBC API를 사용하면 DBMS의 종류에 상관없이 데이터베이스 작업을 처리할 수 있다.

        ➡️ 데이터베이스 관리시스템(DBMS)의 종류 상관없이 동일하게 사용할 수 있는 클래스와 인터페이스로 구성되어 있기 때문

   ⚡️ JDBC API는 java.sql.* 패키지에 의해 구현되며, 이 패키지는 여러 종류의 데이터베이스에 접근 할 수 있다.

        ※ java.sql.* 패키지는 단일 API를 제공하는 클래스와 인터페이스의 집합

 

 

 

 
 

1) DB 연결

 

👾 클라이언트 프로그램에서 DB와 연결하려면 해당 DBMS의 JDBC Driver가 필요

 

  📌  연결에 필요한 정보

    a. DBMS가 설치된 컴퓨터(서버)의 IP 주소

    b. DBMS가 허용하는 포트(Port) 번호

    c. 사용자(DB 계정) 및 비밀번호

    d. 사용하고자 하는 DB 이름

 

 

 

2) JDBC에 포함되어 있는 클래스와 인터페이스

 

출처 : 책 '이것이 자바다'

 

 

(1) DriverManager

  - JDBC Driver를 관리하며 DB와 연결해서 Connection 구현 객체를 생성

 

(2) Connection

  - Statement, PreparedStatement, CallableStatement 구현 객체를 생성하며 Transaction 처리 및 DB 연결을 끊을 때 사용

 

(3) Statement

   - 주로 변경되지 않는 정적 SQL 문을 실행할 때 사용

 

(4) PreparedStatement

    - 매개변수화된 SQL 문을 사용할 수 있기 때문에 편리성과 보안성이 좋음

    - SQL 문을 미리 만들어 두고 변수를 따로 입력하는 방식으로 효율성이나 유지 보수 측면에서 유리

    - 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스의 모든 메서드를 모두 사용할 수 있음

 

(5) CallableStatement

    - DB에 저장되어 있는 프로시저(procedure)와 함수(function)를 호출할 때 사용

 

(6) ResultSet

   - DB에서 가져온 데이터를 읽을 때 사용

 

 


 

 

3) JDBC 프로그램 개발 절차

 

 

👾 JDBC 뿐만 아니라 오픈소스 라이브러리나 프레임워크 등을 이용해서 프로그램을 작성한다는 것은 해당 라이브러리나 프레임워크의 구조와 성격을 이해하고, 제기하는 규격이나 구조에 맞게 프로그램을 만들어야 함을 의미



  📌  1단계 : JDBC 드라이버 로드

   

    · 데이터베이스를 접속하려면 먼저 해당 데이터베이스의 JDBC driver를 로딩

    · 이런 과정이 필요한 이유는 JDK에 포함된 JDBC는 실제 구현 내용이 빠진 스펙만 인터페이스로 포함 하기 때문

        ➡️ 실제로 동작하려면 각 데이터베이스 공급업체에서 구현한 클래스들을 사전에 로딩해야 함

    · Class.forName() 메서드를 사용

 

// MySQL 버전
Class.forName("com.mysql.cj.jdbc.Driver");
 

 

  ⚡️ 이 과정에서 JDBC Driver 클래스의 static 블록이 실행되면서 Driver Manager에 JDBC Driver 객체를 등록하게 된다.

 

// static 블록
class MysqlDriver {
    static {
       Driver driver = new MysqlDriver();
       DriverManager.registerDriver(driver);
    }
}
 

  ⚡️ DriverManager에 JDBC Driver가 등록되면 getConnection() 메소드로 DB와 연결할 수 있다.

 

 


 

  📌  2단계 : 데이터베이스 연결

     · 데이터베이스를 연결하려면 몇 가지 추가 정보가 필요

 

    ① JDBC URL

       - JDBC URL은 다양한 데이터베이스 정보를 포함

       - 각 데이터베이스별로 JDBC URL이 다르므로, 사용하는 데이터 베이스 매뉴얼을 참고하여 작성

 

jdbc:<서브 프로토콜>:<데이터 원본 식별자>

// MySql의 형식
jdbc:mysql://DB 서버의 IP/스키마(데이터베이스):PORT
ex) jdbc:mysql://localhost:3306/sample
 

    🔎  IP주소 : MySql 데이터베이스가 설치된 컴퓨터의 IP 주소 또는 도메인 이름

    🔎  스키마 : 데이터베이스에서 생성된 스키마(데이터베이스) 이름

    🔎  PORT : 기본 설정값인 3306 포트를 사용할 때는 생략 가능

 

 

    ② Connection 클래스 인스턴스 래퍼런스 얻기

       - DriverManager의 getConnection 메서드를 사용

 

Connection conn = DriverManager.getConnection(JDBC URL,"아이디", "비밀번호");
 
 
 

🔎 JDBC URL : 해당 데이터베이스에 맞게 미리 정의한 문자열

🔎 아이디와 비밀번호 : 데이터베이스 자체에서 관리하는 계정

      ➡️ 옆에 사진에 나와 있는 것처럼 보통 아이디는 " root " 비밀번호는 mysql 설치할때 입력한 비밀번호 뜻함

 

 

 

 

 

 

 

 

 


 

 

  📌  3단계 : Statement 생성

     · Statement는 데이터베이스를 연결하여 SQL문을 수행할 수 있도록 하는 클래스

     · 대표적으로 아래 메서드를 사용

 

    ① executeQuery()

      - SELECT 문을 수행할 때 사용

      - 반환값은 ResultSet 클래스의 인스턴스로, 해당 SELECT 문의 결과에 해당하는 데이터에 접근할 수 있는 방법을 제공

      - 단독으로 사용하기 보다는 ResultSet과 함께 사용할 때가 많다

 

String sql = "select * from test";
Statement stmt = conn.createStatement();
stmt.executeQuery(sql);
 
 

    ② executeUpdate()

      - UPDATE 문, DELETE 문 등을 수행할 때 사용

      - 반환값은 int형 데이터로, 처리된 데이터 수를 반환

 

Statement stmt = conn.createStatement();

stmt.executeUpdate("insert into test values (' " +
getUserName() + " ', ' " + getEmail() + " ') ");
 

 

👾 사용자 입력값을 포함해야 할 때는 SQL 문을 변수와 결합해서 만들어야 하므로 코드가 다소 복잡해짐

      ➡️ 컬럼 수가 많아지면 코드 작성이나 유지보수가 어려움

👾 복잡한 SQL 문을 사용할 때는 Statement의 향상된 기능을 제공하는 PreparedStatement을 사용

 

 

    ③ PreparedStatement

        - PreparedStatement는 SQL 문을 미리 만들어 두고 변수를 따로 입력하는 방식

        - 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스의 메서드를 모두 사용

 

PreparedStatement pstmt = conn.preparedStatement("insert
into test values(?, ?) ");
pstmt.setString(1, getUserName());
pstmt.setString(2, getEmail());
pstmt.executeUpdate();
 

 

  🔎 행은 늘어났지만 Statement를 사용할때 보다는 프로그램이 간결해짐

  🔎 SQL 문에서 변수가 와야 할 위치에는 물음표만 적어 두고, 물음표자리에는 setXxx() 메서드로 값을 설정

        ➡️ Xxx에는 String, Int 와 같이 자료형별로 다르게 들어감

 

 

    ④ Statement의 close()

       - 다른 JDBC 리소스와 마찬가지로 Statement 역시 사용하지 않을 때는 닫아 주어여 함

       - PreparedStatement도 마찬가지

 

stmt.close();
pstmt.close();
 

 

 

 

  📌  4단계 : SQL 문 전송

     · 데이터를 입력, 수정, 삭제하려고 SQL문을 만들때는 PreparedStatement를 사용하여 변수와 적절히 조합하면 됨

         ➡️ executeUpdate() 메서드를 사용

 

int count = pstmt.executeUpdate();
 

  💡 이 때 executeUpdate() 메서드는 처리한 로우의 개수를 반환

         ➡️ 처리된 항목이 없다면 0을 반환

  💡 처리 결과는 반환값을 받아서 확인해야 하고, 그럴 필요가없다면 굳이 반환을 받지 않아도 됨

 

 

 

  📌  5단계 : 결과받기

    · 데이터베이스에서 데이터 결과를 받으려면 Statement나 PreparedStatement의 executeQuery()를 사용

    · 입력, 수정, 삭제와 달리 데이터를 가져올 때는 가져온 결과 데이터를 처리하는 ResultSet 객체가 필요

 

ResultSet rs = pstmt.executeQuery():
 

 

  💡 ResultSet은 데이터베이스 내부적으로 수행한 SQL 문의 처리 결과를 JDBC에서 쉽게 관리할 수 있게 함

  💡 필요한 데이터를 모두 가져온 후 ResultSet을 close()하고나서 connection을 close() 해야 함

  💡 ResultSet은 next() 메서드를 사용하여 다음 로우로 이동

        ➡️ 커서를 최초 데이터의 위치로 이동시키려면 ResultSet을 사용하기 전에 rs.next() 메서드를 한 번 호출

 

  · 대부분은 다음과 같이 executeQuery() 메서드를 수행한 후 while(rs.next())와 같이 더 이상 로우가 없을 때까지 루프를 돌면서 데이터를 처리하는 방법을 사용. 이 때 로우에서 각 컬럼값을 가져오려면 rs.getXxx() 메서드를 사용

 

ResultSet rs = psmt.executeQuery();
while(rs.next()) {
  name = rs.getString(1); // or rs.getString("name");
  age = rs.getInt(2); // or rs.getInt("age");
}
rs.close();
 

  🔎 getXxx() 메서드에서 컬럼을 지정하는 방법으로 해당 컬럼의 index 값(1부터 시작) 이나 컬럼 이름을 사용

  🔎 가급적 index보다는 컬럼 이름을 사용하는 편이 코드 이해나 유지보수에 더 유리

  🔎 ResultSet의 사용이 끝났으면 rs.close() 메서드를 사용하여 ResultSet을 닫아 주어야

 

 

 

  📌  6단계 : 연결 해제

     · 데이터베이스와 연결을 관리하는 Connection 인스턴스는 사용한 후 반납하지 않으면 계속 연결을 유지

     · 데이터베이스 연결은 해당 연결을 이용한 작업이 모두 끝나는 시점에서 close() 메서드를 사용하여 해제해야 함

 

conn.close();
 

 

 

 

4) 주요 클래스

 

 

(1) Statement 주요 메서드

 
boolean execute(String sql)
👾 주어진 SQL문 sql을 실행
  - select 구문을 실행하는 경우에는 true를 리턴, 그렇지 않은 경우에는 false 리턴
  - true를 리턴하는 경우에는 getResultSet() 메서드를 이용하여 ResultSet 객체를 생성
  - update, insert, delete 구문을 사용하는 경우에는 false를 리턴하고, getUpdateCount() 메서드를 이용하여 영향받은 행의 갯수를 알아낼수 있음
ResultSet executeQuery(String sql)
👾 select 구문을 실행할 때 사용
int executeUpdate(String sql)
👾 select를 제외한 나머지 insert, create, update, delete 구문을 실행할 때 사용
  - 이 때 영향을 받은 행의 개수를 리턴
ResultSet getResultSet()
👾 현재 SQL 구문을 실행한 결과를 리턴
  - select 구문을 실행했을 경우에만 유효
int getUpdateCount()
👾 현재 SQL 구문의 실행으로 영향을 받은 행의 개수를 리턴
  - select를 제외한 나머지 구문에서만 유효

 

 

 

 

(2) ResultSet

 

 

👩🏻‍💻 Statement 객체의 getResultSet(), executeQuery() 메서드가 리턴하는 객체로서 select 구문 실행 결과를 다룰 때 사용

👩🏻‍💻 select 구문을 실행하여 ResultSet 객체가 생성되면 커서 cursor 가 만들어지고 select 구문 실행 결과를 가르킴

 

 
boolean next()
👾 커서를 다음 행으로 이동
  - ResultSet 객체가 처음 생성된 직후에 next() 메서드를 한 번 호출해야 첫 번째 행을 커서가 가르키게 됨
  - 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 없어서 커서를 이동시킬 수 없으면 false를 리턴
boolean previous()
👾 커서를 이전 행으로 이동
  - 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 결과가 없어서 커서를 이동시킬 수 없으면 false를 리턴
Statement getStatement()
👾 현재 ResultSet을 생성시킨 Statement 객체를 리턴
<자료형> get<자료형>(String colName),
<자료형> get<자료형>(int colIndex)
👾 colName에 지정된 속성명에 해당하는 실제 데이터를 리턴
  - 예를 들어 속성의 데이터 자료형이 String 형과 호환되는 속성이라면 getString() 메서드를
사용
  - 속성 이름 대신 속성의 위치 정보를 colIndex로 줄 수 있음 맨 앞의 속성은 '1', 두 번째 속성은 '2'와 같이 숫자로 속성의 위치를 지정

 

 

 

 

(3) PreparedStatement

 

 

👩🏻‍💻 Statement 객체의 execute계열 메서드는 모두 SQL 문을 컴파일하고 바로 수행시켜서 결과를 리턴

👩🏻‍💻 PreparedStatement 객체는 SQL 문을 미리 컴파일하여 실행하기 직전의 상태로 만든 후 실제 실행은 나중에 필요에 따라 할 수 있음

👩🏻‍💻 같은 SQL 문을 여러 번 실행시켜야 하는 경우에 는 Statement 객체보다 PreparedStatement 객체 사용이 더 효과적

👩🏻‍💻 PreparedStatement 객체로 생성되는 SQL 문은 마치 함수처럼 매개변수를 설정, 필요에 따라 매개변수의 값을 바꿔 실행가능

      ➡️ 비슷한 SQL 구문을 반복적으로 실행시켜야 하는 경우에도 유용

      ➡️ 매개변수를 정의할 때에는 '?' 을 사용하고 매개변수에 값을 설정할때에는 set계열 메서드를 사용

 

 

  📌 DBMS와 Java의 자료형 변환

   · DBMS에서의 컬럼의 자료형과 Java 자료형, 그리고 관련된 JDBC 메소드 간의 변환표

 
DBMS 자료형
Java 자료형
ResultSet 메서드
PreparedStatement 메서드
CHAR
String
getString
setString
VARCHAR
String
getString
setString
DECIMAL
java.math.BigDecimal
getBigDecimal
setBigDecimal
NUMBER
java.math.BigDecimal
getBigDecimal
setBigDecimal
TINYINT
byte
getByte
setByte
SMALLINT
short
getShort
setShort
INTEGER
int
getInt
setInt
BIGINT
long
getLong
setLong
REAL
float
getFloat
setFloat
FLOAT
double
getDouble
setDouble
DOUBLE
double
getDouble
setDouble
DATE
java.sql.Date
getDate
setDate
TIME
java.sql.Time
getTime
setTime
CLOB
Clob
getClob
setClob
BLOB
Blob
getBlob
setBlob
TIMESTAMP
java.sql.Timestamp
getTimestamp
setTimestamp

 

 

 

 

 

 

 

 

[ 내용 참고 : IT 학원 수업 내용 ]

 

 

 

 

+ Recent posts