기록
JDBC 연결 & 사용법 본문
MySQL기준으로 https://downloads.mysql.com/archives/c-j/ 들어가서 버전에 맞게 다운 받습니다.
OS는 Platform Independent로 설정하고 zip파일을 받으면 안에 mysql-connector-j-버전.jar 파일이 있고 그것을 사용합니다.
8.0.32를 사용하였음.
jdbc는 자바에서 DB에 접속할 수 있도록 하는 자바 api입니다.
mysql-connector-j는 jdbc 드라이버 이고, 자바 어플리케이션과 mysql DB간의 통신을 가능하게 해줍니다.
package mysql.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DbConnect {
static final String MYSQLDRIVER = "com.mysql.cj.jdbc.Driver";
static final String MYSQL_URL = "jdbc:mysql://localhost/DB이름?serverTimezone=Asia/Seoul";
public DbConnect() {
try {
Class.forName(MYSQLDRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(MYSQL_URL, "root", "1234");
} catch (SQLException e) {
System.out.println("mysql 연결 실패: " + e.getMessage());
}
return conn;
}
// close가 총 4개의 오버로딩 메서드...conn,stmt(pre),rs(조회문)
public void dbClose(ResultSet rs, Statement stmt, Connection conn) {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void dbClose(ResultSet rs, PreparedStatement pstmt, Connection conn) {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void dbClose(Statement stmt, Connection conn) {
try {
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void dbClose(PreparedStatement pstmt, Connection conn) {
try {
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
위 DbConnect 클래스는 MySQL DB와의 연결을 관리하고 DB작업을 수행하는 메서드를 제공하는 클래스입니다.
String MYSQLDRIVER에는 사용하는 MySQL JDBC 드라이버 클래스의 경로를 의미합니다.
MYSQL_URL은 나의 로컬에 있는 DB의 URL입니다.
아래 DbConnect 생성자는 MySql JDBC 드라이버 클래스를 로드합니다.
Class.forName("com.mysql.cj.jdbc.Driver");
getConnection() 메서드는 사용자의 mysql_url, 이름, 비밀번호를 넘겨서 Connection 객체를 만듭니다.
Connection은 DB와의 연결을 나타내며, sql문이 실행되고 결과를 반환하는 역할을 합니다.
아래 dbClose() 메서드는 ResultSet, Statement, Connection를 받아서 닫아줍니다.
기본적으로 JDBC와 관련된 객체들을 사용한 후에 close하여 메모리 누수를 방지합니다. 자원을 해제하지 않고 남겨두면 메모리를 계속 사용하게 되어 문제가 생길 수 있습니다.
아래는 쿼리문이 작성되어있는 DAO 파일입니다.
dao는 Data Access Object의 약자로 DB에 접근하고 조작하는 객체입니다.
package answer.dogTalking;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import mysql.db.DbConnect;
public class DogTalkingAnswerDao {
// answer.dogTalking 패키지에 속하는 DogTalkingAnswerDao 클래스 시작
DbConnect db = new DbConnect();
// DbConnect 클래스의 객체를 생성하여 데이터베이스 연결을 관리합니다.
// insert
public void insertAnswer(DogTalkingAnswerDto dto) {
// 댓글(DogTalkingAnswerDto 객체)을 삽입하는 메서드 정의 시작
Connection conn = db.getConnection();
// 데이터베이스 연결 객체를 얻어옵니다.
PreparedStatement pstmt = null;
// SQL 문장을 실행하기 위한 PreparedStatement 객체를 선언합니다.
String sql = "insert into dog_talking_answer value(null,?,?,?,now())";
// SQL 문장을 정의합니다.
try {
pstmt = conn.prepareStatement(sql);
// PreparedStatement 객체를 생성하여 SQL 문장을 준비합니다.
pstmt.setString(1, dto.getBoardnum());
pstmt.setString(2, dto.getId());
pstmt.setString(3, dto.getContent());
// SQL 문장의 매개변수를 설정합니다.
pstmt.execute();
// SQL 문장을 실행합니다.
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(pstmt, conn);
// 리소스를 해제합니다.
}
} // 댓글 삽입 메서드 정의 종료
// 총 댓글 수 조회
public int getTotalAnswerCount(String board_num) {
// 총 댓글 수를 조회하는 메서드 정의 시작
int cnt = 0;
Connection conn = db.getConnection();
// 데이터베이스 연결 객체를 얻어옵니다.
PreparedStatement pstmt = null;
ResultSet rs = null;
// 결과 집합을 저장하기 위한 ResultSet 객체를 선언합니다.
String sql = "select count(*) from dog_talking_answer where board_num=?";
// SQL 문장을 정의합니다.
try {
pstmt = conn.prepareStatement(sql);
// PreparedStatement 객체를 생성하여 SQL 문장을 준비합니다.
pstmt.setString(1, board_num);
// SQL 문장의 매개변수를 설정합니다.
rs = pstmt.executeQuery();
// SQL 문장을 실행한 결과를 결과 집합에 저장합니다.
if (rs.next()) {
cnt = rs.getInt(1);
// 결과 집합의 첫 번째 컬럼 값을 가져와서 cnt 변수에 저장합니다.
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(rs, pstmt, conn);
// 리소스를 해제합니다.
}
return cnt;
// 총 댓글 수를 반환합니다.
} // 총 댓글 수 조회 메서드 정의 종료
// 댓글 조회
public List<DogTalkingAnswerDto> showAnswers(String board_num) {
// 댓글을 조회하는 메서드 정의 시작
List<DogTalkingAnswerDto> list = new ArrayList<DogTalkingAnswerDto>();
// DogTalkingAnswerDto 객체를 저장할 리스트를 생성합니다.
Connection conn = db.getConnection();
// 데이터베이스 연결 객체를 얻어옵니다.
PreparedStatement pstmt = null;
ResultSet rs = null;
// 결과 집합을 저장하기 위한 ResultSet 객체를 선언합니다.
String sql = "select * from dog_talking_answer where board_num=? order by idx desc";
// SQL 문장을 정의합니다.
try {
pstmt = conn.prepareStatement(sql);
// PreparedStatement 객체를 생성하여 SQL 문장을 준비합니다.
pstmt.setString(1, board_num);
// SQL 문장의 매개변수를 설정합니다.
rs = pstmt.executeQuery();
// SQL 문장을 실행한 결과를 결과 집합에 저장합니다.
while (rs.next()) {
DogTalkingAnswerDto dto = new DogTalkingAnswerDto();
// DogTalkingAnswerDto 객체를 생성합니다.
dto.setIdx(rs.getString("idx"));
dto.setId(rs.getString("id"));
dto.setBoardnum(rs.getString("board_num"));
dto.setContent(rs.getString("content"));
dto.setWriteday(rs.getTimestamp("writeday"));
// ResultSet에서 가져온 컬럼 값을 객체에 설정합니다.
list.add(dto);
// 리스트에 객체를 추가합니다.
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(rs, pstmt, conn);
// 리소스를 해제합니다.
}
return list;
// 댓글 리스트를 반환합니다.
} // 댓글 조회 메서드 정의 종료
// 댓글 삭제
public void deleteAnswer(String idx) {
// 댓글을 삭제하는 메서드 정의 시작
Connection conn = db.getConnection();
// 데이터베이스 연결 객체를 얻어옵니다.
PreparedStatement pstmt = null;
String sql = "delete from dog_talking_answer where idx=?";
// SQL 문장을 정의합니다.
try {
pstmt = conn.prepareStatement(sql);
// PreparedStatement 객체를 생성하여 SQL 문장을 준비합니다.
pstmt.setString(1, idx);
// SQL 문장의 매개변수를 설정합니다.
pstmt.execute();
// SQL 문장을 실행합니다.
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(pstmt, conn);
// 리소스를 해제합니다.
}
} // 댓글 삭제 메서드 정의 종료
} // answer.dogTalking 패키지에 속하는 DogTalkingAnswerDao 클래스의 정의 종료
많은 dao 파일 중에 특정 게시판의 답변과 관련있는 기능을 하는 메서드로
댓글 추가, 모든 댓글 개수 얻기, 댓글 조회, 댓글 삭제 기능으로 이루어져 있습니다.
첫 줄에
DbConnect db = new DbConnect(); 로 이전에 작성한 DbConnect객체를 얻어와서 DB 연결을 관리합니다.
메서드들이 공통적으로 하는 로직들이 있는데
Connection conn = db.getConnection(); 는 DB를 연결하는 역할을 합니다.
PreparedStatement pstmt = null;
PreparedStatement 클래스는 sql문을 미리 컴파일 하고 저장하여 여러번 실행할 수 있는 기능을 제공합니다.
String sql = "insert into dog_talking_answer value(null,?,?,?,now())";
이것은 sql문으로 적어야 할 것을 적습니다.
null은 자동으로 생성되는것일때 적습니다.
저의 테이블에서는 그 컬럼이 auto_increment로 자동 생성 되는 컬럼입니다.
?는 아래에 set으로 지정되는 값입니다. 이 방식은 실행 시 실제 값으로 대체되는 역할을 합니다. 동적으로 값을 바인딩하여 sql문을 실행 가능합니다.
이 방식은 sql injection 공격을 방지합니다.
pstmt.setString(매개변수 순서, 넣을 값); -> 들어가는 매개변수 값을 설정합니다.
pstmt.execute()는 sql문장을 실행합니다.
위의 코드들은 try catch로 감싸야 합니다.
그 이유는 DB작업은 예상하지 못한 오류가 생길 수 있어서 SQLException을 처리하기 위해 이고, db close로 PreparedStatement와 Connection, ResultSet은 사용 후 반드시 해제해줘야합니다. 해제해야하는 이유는 위에 설명되어있음.
ResultSet rs = null; 의 ResultSet은 DB의 결과의 집합으로 아래의 rs = pstmt.executeQuery(); 로 실행한 결과를 받습니다.
select count(*) from dog_talking_answer where board_num=1
이런식으로 쿼리를 실행하면 결과로
이런식으로 결과가 나옵니다.(현재는 빈 테이블이라 0)
rs = pstmt.executeQuery(); 이렇게 쿼리문을 실행한 결과를 rs에 담고,
if (rs.next())
cnt = rs.getInt(1);
next()를 이용해 rs 내부를 돌 수 있는데
방금 쿼리문은 하나의 컬럼을 가지고있기 때문에 rs.getInt(1)로 접근해서 변수에 담고 그 변수를 반환해줍니다.
showAnswers같은 경우 만약 sql문의 결과가 여러개일 때 사용할 수 있습니다. 위의 코드는 where 문으로 인해 하나만 받을 것입니다.
rs = pstmt.executeQuery(); 실행 후 // execute()는 반환타입이 boolean타입, executeQuery는 ResultSet 타입
while문으로 rs의 내부를 다 도는 동안
미리 생성한 dto로 값들을 받아 list에 add 해줍니다.
where 조건이 없어서 쿼리문의 결과로 여러개의 값들이 나온다면 그 값들모두 List에 담길 것 입니다.
이후 list를 반환합니다.
'DB' 카테고리의 다른 글
윈도우에서 h2 database .db 파일 생성 확인 (0) | 2023.04.22 |
---|