Java

JDBC - insert, select, update, delete문 작성하기(java)

성장코딩 2023. 2. 10. 01:45

Theme. JDBC(Java DataBase Connectivity)란?

 

RDBMS(MySql, Oracle 등) 또는 DBMS에서 작성된 sql문을 실행함으로써 DB에 접근할 수 있는 것은 누구나 알고 있다.

MySql을 예로 들자면,  MySql Workbench에서 sql문을 작성하면서 MySql과 연결/인증, 문장실행, 결과패치 등을 할 수 있다.

이는 다시 말하면, sql문을 작성할 줄 알면 DB에 접근할 수 있다는 것이다.

물론, sql문을 작성할 줄 알아야만 DB에 접근할 수 있는 것은 아니다.

예를 들어, 개발자가 만든 UI를 이용하는 client는 sql문을 작성할 줄도 모르고, 작성해야할 이유도 없을 것이다.

client가 회원목록에서 어떤 회원에 대한 정보를 달라고 하면, 해당 UI를 통해 sql문이 작성되도록 만들면 되기 때문이다. 

Java 프로그래머로서 DB를 이용하려는 사용자의 요구에 부응하는 sql문을 작성해주고, 이를 실행시켜주면 될 것이다.

 

client의 요구를 처리해줄 수 있는 sql문이 작성이 되고, 작성된 sql문과 DB를 연결하기 위해 필요한 것은 DB API이다. 

이때, DB API에 대해 고려해야할 사항이 있다. MySql, Oracle과 같은 RDBMS들이 모두 같은 메서드, 문법을 사용하지 않는다는 것이다. 이로 인해 sql문을 각각에 연결하기 위 DB API가 모두 달라야 한다.

똑같은 sql문을 실행한다고 해도 어떤 (R)DBMS를 쓰냐에 따라 DB API가 달라지게 되고 이는 굉장히 불편할 것이다. DBMS가 바뀌면 새로운 DBMS에 연결하기 위한 DB API에 대해 알아야 하기 때문이다.

 

이때 등장한 것이 바로 "JDBC"이다. RDMBS에 연결하기 위한 모든 코드들은 다 단일화된 JDBC안에 모여있다고 이해하면 쉽다. 이를 통해 연결하고자 하는 RDBMS에 따라 DB API에 대해 알아야 할 필요가 없다. 이제 각각의 DB API들은 JDBC의 Driver가 된다.(JDBC Driver)

 

Theme. JDBC 사용방법

기본적인 코드는 아래의 "순서대로" 사용된다.

1. 드라이버 로드

2. 연결 생성

3. 문장(sql문) 실행

4. 결과집합 사용

 

각각에 대해서 설명하기 전에,

JDBC를 사용하는 과정을 간단하게 설명하자면, UI를 만들고, UI를 통해 사용자의 요구를 파악하며, 그 요구에 따라 sql문을 작성하고 실행하여 DB를 사용하는 것이다. 아래 그림을 살펴보자.

다시 돌아와서 기본적인 코드들을 작성해보면,

1. JDBC 드라이버 로드하기

MySql을 사용하는 경우에는 다음과 같이 작성하면 된다.

Class.forName("com.mysql.cj.jdbc.Driver");

이때, 로드한다는 것의 의미는 클래스를 객체화한다는 의미이다.

그 결과 메모리에 드라이버가 올라가게 될 것이다.

 

2. 연결 생성하기

연결 객체를 얻는 것이다.

Connection conn = DriverManager.getConnection(url, user, password);

예를들면, Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "ABC", "1111");

 

3. sql문 실행 도구 생성하기

Statement st = con.createStatement();

이를 

PreparedStatement psmt = conn.prepareStatement(sql문); 으로 사용할 수 있다.(이 방법으로 코드를 작성하였다)

 

4. 실행 결과를 저장하는 객체 생성하기(결과 집합을 패치)

ResultSet rs = st.executeQuery(sql); 

이는 select, insert, update, delete 등에 따라 사용하는 메서드가 다르다.

// psmt.excuteQuery() : select

// psmt.excuteUpdate() : insert, update, delete ..

 

그림을 통해 과정을 살펴보자.

0. JDBC 사용 전

 

1. 드라이버 로드

Class.forName("com.mysql.cj.jdbc.Driver");

2. 연결 생성

Connection conn = DriverManager.getConnection(url, user, password);

 

 

3. 실행 도구 생성

PreparedStatement psmt = conn.prepareStatement(sql문);

sql문이 실행된다.

 

4. 결과 담을 객체 생성(결과 집합 생성)

ResultSet rs = st.executeQuery(sql); 

sql문이 실행되고 나면 다음과 같은 결과 집합(테이블)이 생성된다. 이는 레코드의 집합이다.

 

서버에서는 결과집합을 사용자에게 한번에 다 돌려주는 것이 아니다. 

결과 집합은 서버에 있는 채로, client는 레코드 단위로 하나씩 받게 된다. 이때 레코드를 가리키는 위의 화살표가 커서이다.

처음 커서는 Before of File에 위치하게 된다.

이때, rs.next(); 가 실행되면, 아래와 같이 커서가 이동하면서 그 레코드를 client에게 전달하게 된다.

이 커서가 End of File에 위치하게 되면 결과 집합을 모두 읽은 것이다.

 

Theme. Insert, select, update, delete문 작성하기

1. DBConnection.java 파일

 - 드라이버를 로드하는 것과 연결 생성하는 과정을 DBConnection이라는 클래스 안에 메서드로 만들어 두었다.

 - initConnection()이라는 메서드를 만들어서 드라이버를 로드한다.

 - getConnection()이라는 메서드를 만들어서 연결을 생성한다.

 

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
31
32
33
34
35
36
37
38
package db;
 
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
public class DBConnection {
 
    public static void initConnection() { // static이니까 언제든지 불러쓸 수 있다.
        
        try {
            Class.forName("com.mysql.cj.jdbc.Driver"); // 드라이버 로드하기
            System.out.println("Driver Loading Success");
        } catch (ClassNotFoundException e) {            
            System.out.println("DB Driver를 찾지 못했습니다");
            e.printStackTrace();
        }    
        
    }
    
    public static Connection getConnection() {
        
        Connection conn = null;    // Connection 객체를 생성
        try {
            // 연결할 url, 데이터베이스 ID, 데이터베이스 PW
            conn = DriverManager.getConnection(url, id, pw); // 실행하는 환경에 따라 입력
            System.out.println("Connection Success");            
        } catch (SQLException e) {            
            System.out.println("db을 연결하지 못했습니다");
            e.printStackTrace();
        }    
        return conn;
    }
    
    
}
 
cs

2. db.sql 파일

 - id, name, age, joindate라는 컬럼 4가지로 테이블을 만들어 두었다.

 - 테이블명은 user이다.

 

3. User.java 파일

client의 정보를 나타내는 객체를 생성하여 사용하고자 만들었다.

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package dto;
 
import java.io.Serializable;
 
public class User implements Serializable{
 
    private String id;
    private String name;
    private int age;
    private String joindate;
    
    public User() {}
 
    public User(String id, String name, int age, String joindate) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.joindate = joindate;
    }
 
    
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getJoindate() {
        return joindate;
    }
 
    public void setJoindate(String joindate) {
        this.joindate = joindate;
    }
    
    @Override
    public String toString() {
        return "UserDto [id=" + id + ", name=" + name + ", age=" + age + ", joindate=" + joindate + "]";
    }
 
    
    
}
 
cs

4. DBClose.java

 실행 중인 객체들을 종료하도록 한다. 주의할 것은 실행된 순서와 반대로 close해줘야 한다는 것이다.

 

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
31
package db;
 
import java.sql.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
 
 
public class DBClose {
 
    public static void close(Connection conn, Statement psmt, ResultSet rs) {
        //사용순서와 반대로 close 함
        try {
            if(rs != null) {
                rs.close();
            }
            if(psmt != null) {
                psmt.close();
            }
            if(conn != null) {    
                conn.close();
            }
        } catch (SQLException e) {                
            e.printStackTrace();
        }            
    }
    
    
    
}
 
cs

 

5. JdbcTest.java

Insert, select, update, delete문을 작성한다.

 

< Insert >

 

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
31
32
33
34
35
36
37
38
39
40
// insert
    public boolean insert(String id, String name, int age) {
        
        // 쿼리문 작성(sql 문장)
        String sql = " insert into user(id, name, age, joindate) "
                + "    values(?, ?, ?, now())  ";
        
        Connection conn = null// 데이터베이스와 연결을 위한 객체
        PreparedStatement psmt = null// sql문을 데이터베이스에 보내기 위한 객체
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            
            psmt = conn.prepareStatement(sql); // sql문 저장
            // DB는 인덱스가 1부터 시작. 위 ? 매개변수에 값을 지정
            // pstmt.set<데이터타입>(? 순서(1부터시작), 값)
            psmt.setString(1, id);
            psmt.setString(2, name);
            psmt.setInt(3, age);
            
            // executeUpdate(): 반환 값은 해당 sql문 실행에 영향을 받는 행 수(레코드 건 수)
            // 그렇게 영향을 받은 행 수를 변수 count에 저장하는 것이다.
            count = psmt.executeUpdate(); 
            
            // psmt.excuteQuery() : select
            // psmt.excuteUpdate() : insert, update, delete ..
            
            System.out.println("성공적으로 추가되었습니다");
            
        } catch (SQLException e) {
            System.out.println("추가되지 않았습니다");
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false;
    }
cs

 

< select >

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// select
    // 1개의 데이터 취득(예를 들면, 1개의 object 취득)
    public User search(String id) {
        
        String sql = " select id, name, age, joindate"
                + "    from user "
                + "    where id = ? ";
        
        Connection conn = null// 데이터 베이스와 연결을 위한 객체
        PreparedStatement psmt = null// SQL 문을 데이터베이스에 보내기위한 객체
        ResultSet rs = null// SQL 질의에 의해 생성된 테이블을 저장하는 객체
        
        User user = null;
        
        try {
            conn = DBConnection.getConnection();
            
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, id); // where id = ?의 ?에 들어갈 id
            
            
            // executeQuery(): ResultSet 객체의 값을 반환
            // executeQuery 메소드는 데이터 베이스에서 가져온 데이터를 resultSet에 담아 그 resultSet을리턴한다.
            rs = psmt.executeQuery();
            
            // rs.next() 를 이용해서 커서를 이동
            if(rs.next()) {
                String _id = rs.getString("id"); // 1이라고 적어도 된다. (select문에서 id, name, age, joindate 순서대로 나왔으므로 1,2,3,4)
                String _name = rs.getString("name");
                int _age = rs.getInt("age");
                String _joindate = rs.getString("joindate");
                
                user = new User(_id, _name, _age, _joindate);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, rs);
        }
        
        return user;
        
    }
    
    // 다수의 데이터 취득 
    public List<User> select() {
        
        String sql = " select id, name, age, joindate "
                + "    from user ";
        
        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;
        
        List<User> list = new ArrayList<User>();
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            rs = psmt.executeQuery();
        
            while(rs.next()) {
                String _id = rs.getString("id");
                String _name = rs.getString("name");
                int _age = rs.getInt("age");
                String _joindate = rs.getString("joindate");
                
                User user = new User(_id, _name, _age, _joindate);
                list.add(user);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, rs);
        }
        
        return list;
        
    }
cs

 

< update >

 

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
31
32
33
// update
    
    public boolean update(String id, String name, int age) {
        
        String sql = " update user "
                + "    set name=?, age=? "
                + "    where id=? ";
        
        Connection conn = null;
        PreparedStatement psmt = null;
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, name);
            psmt.setInt(2, age);
            psmt.setString(3, id);
            
            count = psmt.executeUpdate();
            
        } catch (SQLException e) {
            
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false// return count>0;
        
    }
cs

 

< delete >

 

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
// delete
    public boolean delete(String id) {
        
        String sql = " delete from user where id=?";
                
        Connection conn = null;
        PreparedStatement psmt = null;
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, id);    
            count = psmt.executeUpdate();
            
        } catch (SQLException e) {
            
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false// return count>0;
        
    }
cs

 

이 메서드들을 호출하여 DB에 값을 입력, 검색, 수정, 삭제 등의 작업을 수행할 수 있다.