[JAVA] JDBC1 (Java Database Connectivity)

JDBC, SQL, DB 연동 ,H2

Posted by iheese on April 27, 2022 · 11 mins read


JDBC (Java Database Connectivity)

  • Java에서 DB 프로그래밍을 하기 위해 사용되는 Java API

JDBCDriver

  • JDBC API가 제공하는 인터페이스를 구현한 클래스를 JDBC 드라이버라고 한다.
  • 각 DB에 맞는 JDBC 드라이버가 존재하고 각 DB에서 드라이버(jar 파일: class 파일의 압축파일)를 제공해주므로 DB가 변경되더라도 드라이버만 변경해주면 프로그램의 수정없이 교체할 수 있게 된다.


JDBC 프로그램 순서

  1. JDBC 드라이버 객체 로드
  2. DB 연결
  3. SQL 전송 준비
  4. SQL 전송
  5. DB 연결 종료


JDBC 프로그램 실습

1 . JDBC 드라이버 객체 로드

import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCTest {
	public static void main(String[] args) {
		try {
			DriverManager.registerDriver(new org.h2.Driver());				} catch (SQLException e) {
			e.printStackTrace();
			}
		}
	}
  • h2 DB JDBC 드라이버 객체를 로드했다.
  • DriverManager 클래스의 registerDriver가 SQLException 예외 처리가 필요하므로 try~catch 문으로 처리해줬다.
  • registerDriver에 드라이버 클래스 객체를 생성해주었다.(DB 마다 다른 드라이버 클래스가 존재한다.)


2 . DB 연결

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

public class JDBCTest {

	public static void main(String[] args) {
		Connection conn = null;
		
		try {
			DriverManager.registerDriver(new org.h2.Driver());
			
            String jdbcUrl = "jdbc:h2:tcp://localhost/~/test";
			conn = DriverManager.getConnection(jdbcUrl, "sa", "");                 //JDBC Url, DB 아이디, DB 비밀번호
			
            if(conn != null) {
				System.out.println("Conn 객체의 정보 : " + conn.toString());
		}
       //Conn 객체의 정보 : conn0: url=jdbc:h2:tcp://localhost/~/test user=SA

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
  • getConnection을 이용해 연결할 때는 JDBC URL, DB 아이디, DB 비밀번호를 입력해서 연결하고 conn 객체를 생성한다.
  • if문을 통해 객체가 잘 생성되었는지 정보를 출력해보았다.


3 . SQL 전송 준비

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

public class JDBCTest {

	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement stmt = null;
		
		try {
			DriverManager.registerDriver(new org.h2.Driver());
			
            String jdbcUrl = "jdbc:h2:tcp://localhost/~/test";
			conn = DriverManager.getConnection(jdbcUrl, "sa", "");
			
			String sql = "insert into animal values(?, ?, ?, ?)";
			stmt = conn.prepareStatement(sql);

			if(stmt != null) {
				System.out.println("stmt 객체 정보: " + stmt.toString());
			}    
        //stmt 객체 정보: prep0: insert into animal values(?, ?, ?, ?)
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
  • conn 객체의 prepareStatement 메소드에 sql을 넣어 DB로 보낼 준비를 한다.
  • it문을 통해 stmt 객체에 sql이 잘 들어갔는지 확인했다.
  • (?, ?, ?, ?)는 데이터를 입력하는 파라미터이다. 추후에 setString, setInt 등의 메소드를 통해 값을 입력해준다.


4 . SQL 전송

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

public class JDBCTest {

	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement stmt = null;
		
		try {
			DriverManager.registerDriver(new org.h2.Driver());
			
            String jdbcUrl = "jdbc:h2:tcp://localhost/~/test";
			conn = DriverManager.getConnection(jdbcUrl, "sa", "");
			
			String sql = "insert into animal values(?, ?, ?, ?)";
			stmt = conn.prepareStatement(sql);

			stmt.setString(1, "NUM1");
			stmt.setString(2, "Tory");
			stmt.setInt(3, 5);
			stmt.setString(4, "Dog");
			
			stmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
  • stmt.setString 을 이용해 파라미터에 값을 입력해주고 있다. (첫번째 물음표는 1부터 시작한다.)
  • 각 컬럼의 맞는 데이터 타입을 확인하고 적절한 값을 넣어주어야 한다.
    • DB 테이블의 칼럼이 UNIQUE, PRIMARY KEY 특성이 있는지 잘 확인하지 않으면 에러가 뜰 수 있다.
  • INSERT, UPDATE, DELETE 문 : stmt.executeUpdate() 를 이용해 sql을 DB로 보내 삽입, 수정, 삭제 처리를 할 수 있다.
    • stmt.executeUpdate() 을 int 타입 변수로 받아 출력하면 데이터가 처리된 횟수를 알 수 있다.
  • SELECT 문 : stmt.executeQuery() 를 이용해 sql을 DB로 보내 정보를 조회할 수 있다.
ResultSet rs = null; // ResultSet 초기화
(...)
String sql = "select * from table";
stmt = conn.prepareStatement(sql)
rs=stmt.executeQuery(); //ResultSet에 sql을 통해 데이터를 받아올 수 있다.
while(rs.next()) { 
	System.out.print(rs.getString("COLUMN1")+ ", ");
	System.out.print(rs.getString("COLUMN2")+ ", ");
	System.out.println(rs.getInt("COLUMN3")+ ", ");
	}
		(...)
finally{
	try {
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		(...)
}

ResultSet

  • ResultSet의 구조
    • rs.next()는 다음 행의 값이 존재하면 true, 존재하지 않으면 false를 반환한다.
    • ResultSet은 데이터가 있는 테이블 맨 위(beforeFirst)와 맨 아래(afterLast)에 빈 영역이 존재하는데 ResultSet이 생성될 때 beforeFirst에 위치하게 된다. (그림상의 컬럼명과 데이터테이블 사이)
    • ResultSet의 커서(cursor)는 각 행을 가리키고 next()가 true일 때마다 커서가 한 행씩 내려간다.
    • getString, getInt를 통해 해당 데이터를 받아온다.
  • ResultSet도 마지막에 close()해주어야 한다. (마찬가지로 사용한 역순으로 닫아준다.)


5 . DB 연결 종료

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

public class JDBCTest {

	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement stmt = null;
		
		try {
			DriverManager.registerDriver(new org.h2.Driver());
			
            String jdbcUrl = "jdbc:h2:tcp://localhost/~/test";
			conn = DriverManager.getConnection(jdbcUrl, "sa", "");
			
			String sql = "insert into animal values(?, ?, ?, ?)";
			stmt = conn.prepareStatement(sql);

			stmt.setString(1, "NUM1");
			stmt.setString(2, "Tory");
			stmt.setInt(3, 5);
			stmt.setString(4, "Dog");
			
			stmt.executeUpdate();
            
		} catch (SQLException e) {
			e.printStackTrace();
            
		} finally {
			try {
				stmt.close();
			}catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
  • DB 프로그래밍이 끝나면 사용했던 객체를 close()로 닫아주어야 자원이 낭비되지 않는다.
    • 자원 누수로 인한 오류는 추후에 예상치 못한 오류를 발생할 수 있다.
  • 닫을 때는 선언했던 순서의 반대로 닫아주면 된다. conn 위에서 stmt를 sql을 보냈으므로 stmt을 닫고, conn을 닫아준다.
  • finally을 통해 예외 발생과는 상관없이 실행되게 해준다.


  • JDBC를 통해 SQL문을 보내 DB 프로그래밍을 처리하는 행위는 꽤 길고 복잡한 행위이다. 이 긴 과정을 반복하면 오류가 발생하기 쉬워진다.
  • 위에서 사용했던 코드를 객체를 통해 더 쉽게 사용할 수 있다.
  • [JAVA] JDBC2 (Java Database Connectivity)


Reference: