Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

코딩하는 바나나

[BackEnd] JDBC 본문

Web

[BackEnd] JDBC

유기농바나나칩 2022. 3. 27. 21:07

DAO


DAO는 Data Access Object 즉 데이터에 접근하는 객체이다. 우리는 보통 DAO객체를 구현해서 DB에 접근해서 값을 조회, 수정, 삭제, 삽입 등의 작업을 한다. DAO객체를 따로 서비스 객체와 분리 시켜 DAO는 DB에 접근해서 데이터를 가져오고 서비스 객체는 직접 DB에 접근하지 않고 DAO로 부터 데이터를 받아 비지니스 로직을 적용해준다.

 

JDBC


JDBC는 Java Data Base Connectivity의 약자이다. JDBC를 이용해서 우리는 DB에 접근할 수 있다. 즉 DB(DBMS)에 접근 할 수 있도록 만든 API이다. 보통 DAO객체 안에서 JDBC를 이용한다. 그런데 JDBC를 사용하면 코드가 굉장히 복잡하고 길다. 그리고 반복되는 코드를 계속 사용해줘야한다. 그래서 우리는 보통 그냥 jdbc를 사용하지 않고 Spring JDBC같은 라이브러리를 사용한다. JDBC 만을 사용하면 얼마나 코드가 복잡한지 알아보자.

 

일단 간단히 JDBC를 사용하는 방법만 나열해보면

 

1. DAO클래스와 DTO클래스를 생성한다. DAO클래스는 데이터베이스에 접근을 할 때 사용 할 클래스이고 DTO클래스는 받아온 데이터를 저장할 객체이다. 예를 들어 내가 회원목록DB가 있으면 DAO객체의 함수를 통해 DB에접근해서 DTO객체에 회원 아이디, 이메일 등을 저장하는 것이다.

 

2. DAO클래스의 멤버 변수로 내가 실행시켜놓은 DBMS의 url과 id, 비밀번호를 등록해놓아야한다. 이는 DAO클래스가 DB에 접근 할 때 필요하다. DB url은 사용하는 DBMS별로 다 다르다. MySQL의 경우jdbc:mysql://localhost:3306/[DB이름]?serverTimezone=Asia/Seoul&useSSL=false" 와 같은 형태이다. 로컬이 아닌경우는 IP를 적어주면 된다. 포트번호도 마찬가지로 본인의 DBMS가 사용하는 포트를 등록해주면 된다.

 

3. DB접근에 활용 할 메소드를 정의한다. 예를 들어 아까와 같이 회원목록을 받아오는 함수면, getMember와 같은 함수를 작성한다.

 

4. getMember함수를 이제 구현해야 한다. 먼저 DB에 연결부터 해야한다. 일단 필요한 준비물을 챙겨야한다. Connection객체, PreparedStatement 객체, ResultSet객체가 필요하다. 이 객체들을 먼저 선언해주자. 이것들 모두 java sql라이브러리에 있는 객체이다. 

 

5.위의 객체들을 선언해주었으면 이제 DB연결을 할 수 있다. 먼저 Class.forName("com.mysql.jdbc.Driver")를 작성한다. 당연히 각자 DBMS에 맞게 작성을 해주어야한다. 이 코드는 드라이버를 로딩해주는 역할을 한다. com.mysql.jdbc.Driver 이라는 드라이버 인터페이스를 구현한 클래스(mysql의)를 로딩한 것이다. 

 

6. 이제 내 로컬에서 실행하고 있는 DB와 연결해주어야 한다. 연결한 객체는 아까 미리 생성해 두었던 Connection 객체에 저장한다. 생성한 Connection 객체를 conn이라 하면 conn = DriverManager.getConnection(DBUrl, DBId, DBPassword);를 작성하면 된다. 이렇게 하면 url의 db로 로그인을 시도한다. 우리가 로컬에서 터미널 창을 열어 mysql -u user -p db와 같이 로그인을 하는 과정이라고 생각 하면 된다.

 

7. 이제 로그인을 했으니 쿼리를 작성해야한다. 원하는 쿼리를 String 변수를 하나 정의해 넣어주자 String sql = "select * from role";   

 

8. 이제 이 변수(sql)를 아까 만들어 두었던 연결 객체 conn에 넣어두어야 한다. 그리고 이 연결 객체(conn)을 PreparedStatement(ps) 객체안에 넣어주어햐한다. ps = conn.preparedStatement(sql); 그림과 같이 이해하면 된다.

9. 이제 이 PreparedStatment를 실행해주면 된다. 실행방법은 PreparedStatement의 메소드 executeQuery()를 이용하면된다. 이때 쿼리의 결과를 ResultSet객체(rs)에 받아주면 된다. rs = ps.executeQuery();

 

10. 항상 위의 작업들은 try catch문 안에서 사용해야한다 왜냐하면 DB에 접근 하는 것은 많은 예외 에러들이 발생 할 수 있기 때문이다. 그리고 작업들을 마친 후에는 우리가 미리 선언 해두었던 객체들(ResultSet, PreparedStatement, Connection)을 닫아주어야 한다. 각 객체의 .close()로 닫아주면 된다. 이때 한 가지 주의 할 점은 데이터를 가져오거나 드라이버를 연결을 하는 과정에서 예외가 발생하면 그 뒤에서 초기화 되는 객체들은 아예 생성이 되지 않을 수 있다. 아예 생성이 되지 않을 수 있는 객체를 .close()로 닫으려고 하면 오류가 발생 할 것이다. 따라서 해당 객체가 null이 아닐경우 닫도록 해야한다. 그리고 객체를 사용한 역순으로 닫아 주어야한다. 따라서 ResultSet, PreparedStatement, Connection 순으로 닫아주면 된다.

 

그런데 위의 과정은 내가 보내려는 쿼리에 파라미터가 없는 경우이다. 즉 SELECT * FROM memberTable; 과 같이 모든 값을 받아오게 하는 쿼리는 파라미터가 필요가 없다. 하지만 만약 내가 특정 나이보다 작은 회원의 데이터를 가져오고 싶다고 하면 SELECT * FROM memberTable WHERE age< ? (?안에 원하는 나이를 넣어줘야함)쿼리를 보내야 한다. 이런 경우 실제 sql문을 등록할때 원하는 파라미터의 위치에 위와 같이 ?를 넣어준다. 그리고 ?에 해당하는 부분을 PreparedStatement객체에서 설정 해줄수있다. PerparedStatement의 setInt와 같은 여러 자료형에 따라서 파라미터를 지정해 줄 수 있는 메소드를 제공한다. 파라미터가 여러개여도 setInt(1, 20) (첫번째 파라미터에 int형 20을 넣는다) setString(2, "abc"); (두번째 파라미터에 String형 문자열을 넣는다)와 같이 사용 할 수 있다.

 

 

아래는 위에서 설명한 단계로 작성한 코드이다.

package kr.or.connect.jdbcexam.dao;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

import javax.print.DocFlavor.URL;

import org.w3c.dom.html.HTMLTableRowElement;

import kr.or.connect.jdbcexam.dto.Role;

public class RoleDao {
	private static String dburl = "jdbc:mysql://localhost:3306/connectdb?serverTimezone=Asia/Seoul&useSSL=false";
	private static String dbUser = "connectuser";
	private static String dbpasswd = "connectuser123!@#";
	
	//전체 DB조회
	public List<Role> getRoles(){
			System.out.println("try");

		List<Role> list = new ArrayList();
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection(dburl, dbUser, dbpasswd);
			String sql = "select * from role";
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			
            //db에서 받아온 데이터들 ResultSet에서 내 DTO객체로 변환해서 리스트에 담기
			try {
				while(rs.next()) {
					String description = rs.getString("description");
					int id = rs.getInt("role_id");
					Role role = new Role(id, description);
					list.add(role);
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return list;
	}
    
    //DB에 row추가
	public int addRole(Role role) {
		int insertCount = 0;
		
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			
			Class.forName("com.mysql.jdbc.Driver");
			
			conn = DriverManager.getConnection(dburl, dbUser, dbpasswd);
			
			String sql = "INSERT INTO role (role_id, description) VALUES(?, ?)";
			
			ps = conn.prepareStatement(sql);
			
			ps.setInt(1, role.getRoleId());
			ps.setString(2, role.getDescription());
			
			insertCount = ps.executeUpdate();
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return insertCount;
	}		
}

 

Spring JDBC


위의 코드를 보면 일단 너무 복잡하다. 그리고 중복되는 코드가 굉장히 많다. Spring JDBC는 이런 단점들을 보안해준다. 

다음 게시물에서 Spring JDBC사용법에 대해 알아보자~

'Web' 카테고리의 다른 글

[BackEnd] Spring MVC  (1) 2022.03.29
[BackEnd] Spring JDBC  (0) 2022.03.29
[BackEnd] DB, DBMS  (0) 2022.03.27
[BackEnd] Scope  (0) 2022.03.09
[BackEnd] redirect, foward, servlet jsp연동  (0) 2022.03.09