JDBC 구현
JDBCManager
JDBC를 사용해 Mysql 데이터베이스와의 연결을 관리하는 매니저 클래스
Mysql 데이터베이스 접속에 필요한 정보(사용자이름, 암호, URL) 를 상수로 정의
1
2
3
private static final String USERNAME = "root"; // 데이터베이스 사용자 이름
private static final String PASSWORD = "XXXXXXXX"; // 데이터베이스 암호
private static final String URL = "jdbc:mysql://localhost/XXX?useSSL=false";
- JDBC URL: localhost에 설치된 MySQL 서버의 XXX데이터베이스에 접속
- useSSL=false : SSL 을 사용하지 않음
- 이외 추가 접속 옵션 설정
클래스가 로드될 때 JDBC 드라이버 로드
1
2
3
4
5
6
7
8
9
static { // 클래스가 로드될때 드라이버가 항상 로드되도록 보장하기 위해 정적으로 설정함(필수X)
try {
// Mysql JDBC 드라이버 클래스 로드
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Failed to load JDBC driver");
}
}
데이터베이스 연결
1
2
3
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
- getConnection() 메서드 : 데이터베이스 연결을 생성하고 반환
- DriverManager.getConnection(URL, USERNAME, PASSWORD) 접속정보를 이용해 데이터베이스 연결 요청을 하고 이를 Connection 객체로 반환한다.
JdbcManager.java 전체코드
연결을 했으니까 이제 SQL 쿼리를 실행하는 Java 코드 보겠습니다.
예시로 주문을 insert 하는 쿼리
insertOrder메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ItemDao {
public int insertOrder(String itemId, int quantity, Order order) {
String sql = "INSERT INTO orders (order_id, item_id, stock_count) VALUES (?, ?, ?)";
try (Connection conn = JdbcManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// Order 객체에서 필요한 정보를 가져와서 SQL 문에 설정합니다.
// 주문 insert
pstmt.setString(1, order.getOrderId());
pstmt.setString(2, itemId);
pstmt.setInt(3, quantity);
int count = pstmt.executeUpdate();
// 코드 생략
} catch (SQLException e) {
e.printStackTrace();
// 예외 처리 및 롤백 로직이 필요할 수 있음
}
return 0;
}
}
-
쿼리문 작성 : String sql = “~~~”
?은 PreparedStatement의 매개변수 위치 지정자이다. -
Connection conn = JdbcManager.getConnection();
JdbcManager 클래스의 getConnection() 메서드를 사용하여 데이터베이스와 연결한다. -
PreparedStatement pstPreparedStatement pstmt = conn.prepareStatement(sql)
준비된 문장을 사용하여 SQL 쿼리를 실행할 PreparedStatement 객체를 생성한다. -
pstmt.setString(1, order.getOrderId());
Sql 쿼리의 첫 번째 매개변수에 값을 바인딩한다. -
pstmt.executeUpdate()
sql 쿼리를 실행하고 데이터베이스에 데이터를 삽입한다.
executeUpdate()와 executeQuery()
하나 기억할 점은 각각 데이터 조작 및 조회 작업에 맞게 sql문 실행 메서드를 사용해야 한다. executeUpdate() 메서드는 insert, update, delete 와 같은 DML 쿼리를 실행할 때 사용된다. 반환값으로 영향을 받은 레코드, 행의 개수를 반환한다.
executeQuery() 메서드는 select 쿼리와 같이 데이터베이스 에서 데이터를 조회할 때 사용한다. ResultSet 객체를 반환하며, ResultSet 는 쿼리에 대한 결과 집합을 나타낸다.
?
하지만 이런 형식으로 select, insert, update 메서드를 구현한다며?
커넥션을 획득하고, 매개변수를 매핑하고, 쿼리를 실행하는 동작들이 중복될 것이다. 중복이 너무 많다~~~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class BaseDao<T> {
public <T> T execute(String sql,
ResultSetHandler<T> handler,
Object...params) {
try (Connection conn = JdbcManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
for (int i=0; i<params.length; i++) {
pstmt.setObject(i+1, params[i]);
}
ResultSet rs = pstmt.executeQuery();
return handler.handle(rs);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
제네릭 타입 T를 받는 추상 클래스로 다양한 유형의 데이터를 처리할 수 있다.
- execute() 는 제네릭 메서드로 데이터베이스 쿼리를 실행하고 그 결과를 처리기 위한 메서드
- sql : 실행할 쿼리문
- handler : ResultSet 을 처리할 ResultSetHandler 인터페이스 구현체
- params : 쿼리에 바인딩할 매개변수.
사용 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ItemDao extends BaseDao {
public Item selectOne(String id) {
String sql = "SELECT * FROM item WHERE item_id = ?";
return (Item) execute(sql, rs -> {
if (rs.next()) {
Item item = new Item();
item.setId(rs.getString("item_id"));
item.setName(rs.getString("item_nm"));
item.setPrice(rs.getInt("price"));
item.setStockCount(rs.getInt("stock_count"));
return item;
} else {
return null;
}
}, id);
}
}
1
2
3
4
5
6
@FunctionalInterface
public interface ResultSetHandler<T> {
T handle(ResultSet rs) throws SQLException;;
}