JDBC (Java DataBase Connectivity)
JDBC๋ DB์ ์ ๊ทผํ ์ ์๋๋ก Java์์ ์ ๊ณตํ๋ API๋ก, ๋ชจ๋ Java์ Data Access ๊ธฐ์ ์ ๊ทผ๊ฐ์ด๋ค.
๋ชจ๋ Persistence Framework๋ ๋ด๋ถ์ ์ผ๋ก JDBC API๋ฅผ ์ด์ฉํ๋ค.
JDBC๋ฅผ ํตํ DB ์ฐ๊ฒฐ
1. ๋๋ผ์ด๋ฒ ๋ก๋
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println(" !! JDBC Driver load ์ค๋ฅ: " + e.getMessage());
e.printStackTrace();
}
์ ๊ณต๋๋ ํด๋์ค๋ฅผ ์ธ์คํด์คํํด์ ๋ด๋ถ์ ์ผ๋ก ์ ์ฅํด ๋ฉ๋ชจ๋ฆฌ์ ๋๋ผ์ด๋ฒ๋ฅผ ์ฌ์ฉํ ์ ์๊ฒํ๋ค.
์ด ๋ฉ์๋๋ฅผ ํตํด ๋๋ผ์ด๋ฒ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์ด๊ธฐํ ํ๋ค.
์์ฑ์๋ฅผ ํตํ ์ธ์คํด์ค ์์ฑ๊ณผ ๊ฐ๋ค๊ณ ๋ณผ ์ ์๋ค.
2. Connection ๊ฐ์ฒด ์์ฑ
DriverManager ํด๋์ค๋ ๋๋ผ์ด๋ฒ๋ฅผ ํตํด Conection ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
Connection์ DB์ ์ฐ๊ฒฐํ๋ ๊ฐ์ฒด๋ก DB์ ์ฐ๊ฒฐํ๋ ํต๋ก์ด๋ฉฐ, ์ด๋ฅผ ํตํด ์ฟผ๋ฆฌ๋ฅผ ์ ๋ฌํ๊ณ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํ๋ฐ๋๋ค.
try {
con = DriverManager.getConnection("jdbc:mysql://" + server + "/" + database + option, userName, password);
System.out.println("์ ์์ ์ผ๋ก ์ฐ๊ฒฐ๋์์ต๋๋ค.");
} catch (SQLException e) {
System.err.println("์ฐ๊ฒฐ ์ค๋ฅ:" + e.getMessage());
e.printStackTrace();
}
3. Statement / PreparedStatement ๊ฐ์ฒด ์์ฑ
Statement ๊ฐ์ฒด๋ฅผ ํตํด insert ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ฉด ์๋์ ๊ฐ์ด ๊ฐ๊ฐ์ ๊ฐ์ ์ฝค๋ง์ ๋ฐ์ดํ๋ก ๊ตฌ๋ณํด์ผํ๊ธฐ ๋๋ฌธ์
๊ฐ๋
์ฑ๋ ๋จ์ด์ง๊ณ ์๋ชป ์
๋ ฅํ ํ๋ฅ ๋ ์ปค์ง๋ค.
statement = connection.createStatement();
String query = "INSERT INTO piece(color, name, position, chessGameId) VALUE ('" + color + "','" + name + "','" + position + "','" + chessGameId "')";
resultCount = statement.executeUpdate(insertQuery);
PreparedStatement ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑ ๊ฐ์ ?๋ก ์ค์ ํ๊ณ set์ ํตํด ์ค์ ํ๋ฉด, ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑ์์ผ์ค๋ค.
String query = "INSERT INTO piece(color, name, position, chessGameId) VALUE (?, ?, ?, ?)";
try (Connection connection = dbManager.getConnection();
PreparedStatement pstmt = connection.prepareStatement(query)) {
for (Piece piece : pieces) {
pstmt.setString(1, piece.color().name());
pstmt.setString(2, piece.name());
pstmt.setString(3, piece.position().key());
pstmt.setInt(4, chessGameId);
pstmt.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
executeQuery()
: select๋ฅผ ํตํ ์ ๋ณด๋ฅผ ์กฐํํ๊ณ , ์ฟผ๋ฆฌ๋ฅผ ์ ์ก ํ ๊ฒฐ๊ณผ ๊ฐ์ฒด ๋ฐํํ๋ค.executeUpdate(String query)
: Insert, Update, Delete ์ฟผ๋ฆฌ๋ฅผ ์ ์กํ๊ณ ๋ณ๊ฒฝ๋ ๋ ์ฝ๋ ์๋ฅผ ๋ฐํํ๋ค.
4. ResultSet ๊ฐ์ฒด ๋ฐํ
ResultSet ๊ฐ์ฒด๋ select ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ์ ๋ชจ๋ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด์ด๋ค.
while (rs.next()) {
Piece piece = PieceFactory.findByInfo(rs.getString("color"),
rs.getString("name"), rs.getString("position"));
pieces.add(piece);
}
boolean next()
: ๊ฒฐ๊ณผ ๋ ์ฝ๋๊ฐ ์กด์ฌํ๋ฉด true, ์์ผ๋ฉด falseboolean previous()
: ์ด์ ๋ ์ฝ๋๋ก ์ด๋ (๊ฐ์ฅ ์ฒซ ํ์ด๋ฉด false)boolean first()
: ์ฒ์ ์์น๋ก ์ด๋ (๋ ์ฝ๋๊ฐ ์์ผ๋ฉด false)boolean last()
: ๋ง์ง๋ง ์์น๋ก ์ด๋ (๋ ์ฝ๋๊ฐ ์์ผ๋ฉด false)String getString(String colLabel)
: ํ์ฌ ์ปค์ ์์น์ ์ปฌ๋ผ๋ช ์ ํด๋นํ๋ ๋ฌธ์์ด ๋ฐํint getInt(String colLabel)
: ํ์ฌ ์ปค์ ์์น์ ์ปฌ๋ผ๋ช ์ ํด๋นํ๋ ์ ์๊ฐ ๋ฐํString getString(int colIndex)
: ์ปฌ๋ผ ์ธ๋ฑ์ค์ ํด๋นํ๋ ๋ฌธ์์ด ๋ฐํ (1๋ถํฐ ์์)int getInt(int colIndex)
: ์ปฌ๋ผ ์ธํ ์ค์ ํด๋นํ๋ ์ ์๊ฐ ๋ฐํ (1๋ถํฐ ์์)
5. ์์ ํด์
DB ๊ด๋ จ ์์
์ ํ๋ฉด์ Connection, Statement / PreparedStatement, ResultSet ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ค.
DB ๊ด๋ จ ์ฒ๋ฆฌ ์์
์ด ์๋ฃ๋์๋ค๋ฉด, ์ฌ์ฉํ๋ ๊ฐ์ฒด๋ค์ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ํด์ฃผ์ด์ผ ํ๋ค.
๋ง์ฝ ํด๋น ์์๋ค์ ํด์ ํด์ฃผ์ง ์์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ์ด ๋ฐ์ํ ์ ์๋ค.
- Connection pool์ ์ฌ์ฉํ์ง ์์ ์ํ์์ Connection์ ๋ซ์ง ์์ผ๋ฉด DBMS์ ์ฐ๊ฒฐ๋ ์๋ก์ด Connection์ ์์ฑํ ์ ์๋ค.
- Statement / PreparedStatement๋ฅผ ํด์ ํ์ง ์์ผ๋ฉด, ์์ฑ๋ ๊ฐฏ์๊ฐ ์ฆ๊ฐํ๋ฉด์ ๋ ์ด์ ์๋ก์ด Statement / PreparedStatement๋ฅผ ์์ฑํ ์ ์๋ค.
์ด๋ฒ ๋ฏธ์
์์๋ try-with-resource๋ฅผ ํตํด ์์ close ์ฒ๋ฆฌ ๊ฐ์ ์ ํ์๋ค.
์ด๋ try ๋ธ๋ก์ ์๊ดํธ ์์์ ์์ ํด์ ๊ฐ ํ์ํ ๊ฐ์ฒด๋ฅผ ํ ๋นํ๋ฉด try catch ์ ์ด ์ข
๋ฃ๋๋ฉด์
์์ ํด์ ๊ฐ ํ์ํ connection๊ณผ preparedstatement๋ฅผ ์๋์ผ๋ก close๋๋ try-catch ๋ฌธ์ด๋ค.
preparedstatement๋ฅผ ํด์ ํ๋ฉด ํ์ฌ(๊ฐ์ฅ ์ต๊ทผ์ ์์ฑํ) ResultSet๋ ์๋์ผ๋ก ํด์ ๋๋ค.
public List<Piece> findAllByChessGameId(int chessGameId) {
List<Piece> pieces = new ArrayList<>();
String query = "SELECT color, name, position FROM piece WHERE chessGameId = ?";
try (Connection connection = dbManager.getConnection();
PreparedStatement pstmt = connection.prepareStatement(query)) {
pstmt.setInt(1, chessGameId);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
Piece piece = PieceFactory.findByInfo(rs.getString("color"),
rs.getString("name"), rs.getString("position"));
pieces.add(piece);
}
} catch (SQLException e) {
e.printStackTrace();
}
return pieces;
}
SQL Exception์ ๋ํ์ฌ
checked exception์ธ SQLException์ ๋ํด ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋ฅผ ํ ์ง ๊ณ ๋ฏผํ๋ค๊ฐ ๊ฒฐ๊ตญ ์ธ๋ถ๋ก ๋์ ธ์ฃผ๊ธฐ๋ง ํ์๋ค.
ํด์ ํผ๋๋ฐฑ๋๋ก ์ง๊ธ์ DAO์์ stacktrace๋ง ์ถ๋ ฅํ๋๋ก ๋ณ๊ฒฝํ์๋ค.
์ถํ์ ํด๊ฐ SQLException์ ๋ํ ์ฐธ๊ณ ์๋ฃ๋ฅผ ๋ณด๋ด์ฃผ์
จ๋ค.
[Toby spring] ์ฌ๋ผ์ง SQLException์ ๋ฐ๋ฅด๋ฉด DAO์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ๊ณ์ํด์ ์ธ๋ถ๋ก ๋์ ธ์ฃผ๋ ๊ฒ๋ ํ๋์ ๋ฐฉ๋ฒ์ด์ง๋ง,
์ด๋ ๊ฒ ๋๋ฉด ์์ธ๊ฐ ๋ฐ์ํ DAO๋ฅผ ์ฌ์ฉํ Service์์ ์ SQLException์ด ๋ฐ์ํ๋์ง ์ ์ ์๊ธฐ ๋๋ฌธ์
์๋์ ๊ฐ์ด SQLException์ ํฌ์ฅํ ์์ธ์ ์๋ฏธ๋ฅผ ๋ด์ ์ปค์คํ
์์ธ๋ฅผ ๋ง๋ค์ด ๋์ ธ์ฃผ๋ ๊ฒ๋ ํ๋์ ๋ฐฉ๋ฒ์ด ๋ ์ ์๋ค.
์ด๋ ๊ฒ ๋๋ฉด ์๋ฏธ๊ฐ ๋ถ๋ช
ํ ์์ธ๋ก ์ ๋ฌํด์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ค.
try {
//...
} catch (SQLException e) {
throw DuplicatePieceIdException(e);
}
try {
//...
} catch (SQLException e) {
throw DuplicatePieceIdException().initCause(e);
}
๋ ์๋ฃ์ ๋ฐ๋ฅด๋ฉด JDBCTemplate์ ์ฌ์ฉํ๋ฉด ์ด ๋ด๋ถ์์ SQLException์ ์ฒ๋ฆฌํด์ค๋ค๊ณ ํ๋ ์ฐจ์ฐจ ๊ฐ๋ ์ ์์๊ฐ์.