Backend
home

2024. 7. 31

데이터베이스 입출력

Java는 DB와 연결해서 데이터 입출력 작업을 할 수 있도록 JDBC(Java Database Connectivity) 라이브러리를 제공한다.
JDBC Driver : JDBC 인터페이스를 구현한 것으로 DBMS마다 별도로 라이브러리를 다운로드 받아 사용해야 한다.
DB 연결을 위해서는 IP 주소, DBMS 포트번호, 사용자 이름 및 비밀번호, 접속하려는 DB 이름이 필요하다.
DriverManager 클래스
JDBC Driver를 등록 및 관리하고, DB와 연결을 생성하는 클래스
정적메소드 getConnection()을 통해 연결하고, Connection 구현 객체를 반환한다.
String url = "jdbc:mysql://localhost:3306/kostagram"; String user = "root"; String password = "1234"; Connection conn = DriverManager.getConnection(url, user, password);
Java
복사
Connection 인터페이스
DB 연결을 나타내는 인터페이스
SQL에 요청할 객체를 생성할 때 사용된다.
createStatement() 메서드로 Statement 구현 객체를 반환한다.
prepareStatement() 메서드로 PreparedStatement 구현 객체를 반환한다.
Statement stmt = conn.createStatement(); String sql = "SELECT * FROM users where id = ?"; PreparedStatement pstmt = conn.prepareStatement(sql);
Java
복사
Statement 인터페이스
executeQuery( ) 메소드를 통해 SQL문 실행 요청을 하고, 결과를 ResultSet 구현 객체로 반환한다.
주로 정적 SQL문을 실행할 때 사용된다.
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
Java
복사
PreparedStatement 인터페이스
setXXX() 메소드로 SQL문에 ‘?’ 표시된 파라미터 값을 설정한다.
executeQuery() 메소드를 통해 SQL문 실행 요청을 하고, 결과를 ResultSet 구현 객체로 반환한다.
pstmt.setInt(1, 1); ResultSet rs = pstmt.executeQuery();
Java
복사
ResultSet 인터페이스
SQL문의 실행 결과를 나타내는 인터페이스이다.
next() 메소드로 결과 집합의 다음 레코드로 이동한다.
getXXX() 메소드로 결과 집합의 값을 가져온다.
while (rs.next()) { System.out.println( rs.getInt("id") + "\t" + rs.getString("email") + "\t" + rs.getString("nickname") + "\t" + rs.getString("password") ); }
Java
복사

DB 연동

Java와 DBMS를 연동하면, 값을 저장하고, 데이터를 가져오고, 수정 또는 삭제를 하는 작업을 Java에서 할 수 있게 된다.
Java에 작성된 특정 코드가 실행되면, 지정된 DBMS으로 쿼리를 전송하고 결과를 얻어 오는 것이다.
Java를 통해 데이터베이스에 접근할 수 있는 별도의 프로그램을 하나 만드는 것이다.

DB 연결

해당 DBMS의 JDBC Driver
DBMS가 설치된 컴퓨터의 IP 주소
DBMS가 허용하는 포트(Port) 번호
DB 사용자 계정 및 비밀번호
사용하고자 하는 DB 이름

DB 연결

Driver 연결 후 코드 작성
package db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBConnection { public static Connection conn = null; public static void main(String[] args) throws ClassNotFoundException { String server = "localhost"; // 서버 주소 String user_name = "root"; // 접속자 id String password = "Dmove1122!"; // 접속자 pw // JDBC 드라이버 로드 try { // 1. 드라이버 로딩 // 새로운 드라이버명으로 변경됨 "com.mysql.jdbc.Driver" => "com.mysql.cj.jdbc.Driver" Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { System.err.println("JDBC 드라이버를 로드하는데에 문제 발생" + e.getMessage()); e.printStackTrace(); } // 접속 // 2. DB 연결 try { conn = DriverManager.getConnection("jdbc:mysql://" + server + "/" + "?useSSL=false" + "&allowPublicKeyRetrieval=true&useUnicode=true&serverTimezone=UTC", user_name, password); System.out.println("연결 완료!"); } catch (SQLException e) { System.err.println("연결 오류" + e.getMessage()); e.printStackTrace(); } // 접속 종료 try { if (conn != null) conn.close(); System.out.println("연결 종료"); } catch (SQLException e) { e.printStackTrace(); } } }
Java
복사
select 문 실행
try { conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/kostagram", user_name, password); Scanner sc = new Scanner(System.in); // statement 생성 Statement stmt = conn.createStatement(); System.out.print("이메일 입력 : "); String userEmail = sc.nextLine(); System.out.print("비밀번호 입력 : "); String userPassword = sc.nextLine(); String sql = "SELECT * FROM users WHERE email = '" + userEmail + "' AND password = '" + userPassword + "'"; ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { System.out.println(rs.getString("name")); } else { System.out.println("로그인 실패"); } System.out.println("연결 완료!"); } catch (SQLException e) { System.err.println("연결 오류" + e.getMessage()); e.printStackTrace(); }
Java
복사
SQL Injection 확인
statement는 활용하지 않음
Statement stmt = conn.createStatement(); System.out.print("이메일 입력 : "); String userEmail = sc.nextLine(); System.out.print("비밀번호 입력 : "); String userPassword = sc.nextLine(); String sql = "SELECT * FROM users WHERE email = '" + userEmail + "' AND password = '" + userPassword + "'"; 이메일 입력 : ryu@gmail.com' or '1'='1 비밀번호 입력 : 12312412412 류준열 연결 완료!
Java
복사
PreparedStatement로 변경 후 SQLInjection 막음
String sql = "SELECT * FROM users WHERE email = ? and password = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, userEmail); pstmt.setString(2, userPassword); ResultSet rs = pstmt.executeQuery(); 이메일 입력 : ryu@gmail.com' or '1'='1 비밀번호 입력 : 1234 로그인 실패 연결 완료!
Java
복사

데이터 삽입

users 테이블에 새로운 사용자 정보(id, email, name, password)를 저장해보자.
값을 ?(물음표)로 대체한 매개변수화된 INSERT문은 아래와 같다.
INSERT INTO users (name, email, password) VALUES (?, ?, ?)
Java
복사
위의 INSERT문 을 String 타입 변수로 대입한다.
String sql = new StringBuilder() .append("INSERT INTO users (name, email, password) ") .append("VALUES (?, ?, ?)") .toString(); String sql = "INSERT INTO users (name, email, password) " + "VALUES (?, ?, ?)"; String insertSql = "INSERT INTO users (name, email, password) VALUES (?, ?, ?)"; PreparedStatement pstmt = conn.prepareStatement(insertSql); Scanner sc = new Scanner(System.in); System.out.print("이름 : "); String userName = sc.nextLine(); System.out.print("이메일 : "); String userEmail = sc.nextLine(); System.out.print("비밀번호 : "); String userPassword = sc.nextLine(); pstmt.setString(1, userName); pstmt.setString(2, userEmail); pstmt.setString(3, userPassword); int insertedRow = pstmt.executeUpdate(); System.out.println(insertedRow + "개의 회원 정보가 추가되었습니다 uh."); sc.close(); pstmt.close(); 이름 : 침착맨 (id = 5) 이메일 : chim@gmail.com 비밀번호 : 1234 1개의 회원 정보가 추가되었습니다 uh.
Java
복사
값을 지정한 후, PreparedStatement의 executeUpdate( ) 메소드를 호출하면, SQL문이 실행되면서 users 테이블에 1개의 행이 저장된다.
int resultRow = pstmt.executeUpdate();
Java
복사
executeUpdate( ) 메소드는 저장된 행의 개수를 int 값으로 반환한다. 즉, 정상적으로 실행된 경우에는 1을 반환한다.
posts 테이블 Insert
// 침착맨 글쓰기 String sql = "INSERT INTO posts (user_id, content, image) VALUES (?, ?, ?)"; PreparedStatement pstmt = conn.prepareStatement(insertPostSql); System.out.print("사용자 아이디 번호 : "); pstmt.setInt(1, sc.nextInt()); System.out.print("게시글 내용 : "); pstmt.setString(2, sc.nextLine()); System.out.print("게시글 이미지 파일명 : "); pstmt.setString(3, sc.nextLine()); int resultRow = pstmt.executeUpdate(); System.out.println(resultRow + "개의 포스팅 정보가 추가되었습니다 uh."); 내용 : 침착맨입니다. 이미지 : image.png 1개의 포스팅 정보가 추가되었습니다 uh.
Java
복사
post 테이블 Insert 코드 재정리
// 침착맨 글쓰기 // 1. 사용자 아이디 번호 입력 받기 System.out.print("사용자 아이디 번호 : "); int user_id = sc.nextInt(); // 2. 사용자 아이디 번호를 통한 사용자 이름 조회 PreparedStatement nameStmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?"); nameStmt.setInt(1, user_id); ResultSet rs = nameStmt.executeQuery(); // 3. 사용자 이름 조회 결과가 있으면 해당 블록 실행 if (rs.next()) { // 3-1. 사용자 이름 가져오기 String userName = rs.getString("name"); // 3-2. 게시물 작성 String insertPostSql = "INSERT INTO posts (user_id, content, image) VALUES (?, ?, ?)"; PreparedStatement postStmt = conn.prepareStatement(insertPostSql); // 3-3. 게시글 내용, 이미지 파일명 입력받기 System.out.print("게시글 내용 : "); sc.nextLine(); // nextInt 이후의 비우기 (새로운 입력 준비) String content = sc.nextLine(); System.out.print("게시글 이미지 파일명 : "); String image = sc.nextLine(); // 3-4. ? 파라미터에 입력값 대입 postStmt.setInt(1, user_id); postStmt.setString(2, content); postStmt.setString(3, image); // 3-5. INSERT 실행 및 결과 출력 int insertedRow = postStmt.executeUpdate(); System.out.println(userName + "이 작성한 " + insertedRow + "개의 게시글이 추가되었습니다."); // 3-6. 리소스 종료 postStmt.close(); } else { // 4. 사용자 이름이 조회되지 않는 경우 System.out.println("없는 사용자입니다."); } rs.close(); sc.close(); nameStmt.close();
Java
복사

데이터 수정

// 특정 게시물 내용 수정 // 1. 특정 게시물 내용 수정하기 위한 SQL문 작성 String updateSQL = "UPDATE posts SET content = ? WHERE id = ?"; // 2. SQL을 이용해 PreparedStatement 생성 PreparedStatement updateStmt = conn.prepareStatement(updateSQL); // 3. 입력을 통해, 수정 내용과 게시물 번호 받아오기 System.out.print("수정할 게시물 번호 : "); int post_id = sc.nextInt(); sc.nextLine(); System.out.print("수정할 내용 : "); String content = sc.nextLine(); // 4. ? 파라미터에 값 대입 updateStmt.setString(1, content); updateStmt.setInt(2, post_id); // 5. 실행 및 실행 결과 출력 int updatedRow = updateStmt.executeUpdate(); System.out.println("게시물 " + updatedRow + "개가 수정되었습니다."); // 6. 자원 해제 updateStmt.close();
Java
복사

데이터 삭제

// 게시물 삭제 // 1. SQL문 작성 String deleteSql = "DELETE FROM posts WHERE id = ?"; // 2. 입력받기 System.out.println("게시물 번호 : "); int post_id = sc.nextInt(); // 3. PreparedStatement 생성 PreparedStatement deleteStmt = conn.prepareStatement(deleteSql); // 4. ?에 값 넣기 deleteStmt.setInt(1, post_id); // 5. 실행 int deletedRow = deleteStmt.executeUpdate(); System.out.println(deletedRow + "개의 게시물이 삭제되었습니다."); // 6. 자원해제 deleteStmt.close(); sc.close();
Java
복사

데이터 조회

// 전체 회원 조회 String allUserSql = "SELECT * FROM users"; // ResultSet rs = conn.prepareStatement(allUserSql).executeQuery(); PreparedStatement userStmt = conn.prepareStatement(allUserSql); ResultSet rs = userStmt.executeQuery(); while (rs.next()) { System.out.println("------------------------------------"); System.out.println(rs.getInt("id")); System.out.println(rs.getString("name")); System.out.println(rs.getString("email")); System.out.println(rs.getString("password")); System.out.println("------------------------------------"); } rs.close(); userStmt.close(); sc.close();
Java
복사

실습

회원가입
package db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Scanner; public class DBConnection2 { public static Connection conn = null; public static void main(String[] args) { // 접속자 id String user_name = "root"; // 접속자 pw String password = "Dmove1122!"; // url String url = "jdbc:mysql://localhost:3306/kostagram"; // JDBC 드라이버 생성 try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { System.err.println("JDBC 드라이버를 로드하는데 문제 발생" + e.getMessage()); } // DB 연결 try { conn = DriverManager.getConnection(url, user_name, password); Scanner sc = new Scanner(System.in); System.out.println("DB 연결 성공!"); // CRUD // 회원가입 (C) String insertSql = "INSERT INTO users (name, email, password) " + "VALUES(?, ?, ?)"; PreparedStatement insertPstmt = conn.prepareStatement(insertSql); System.out.print("이름 입력 : "); String userName = sc.nextLine(); System.out.print("이메일 입력 : "); String userEmail = sc.nextLine(); System.out.println("비밀번호 입력 : "); String userPassword = sc.nextLine(); insertPstmt.setString(1, userName); insertPstmt.setString(2, userEmail); insertPstmt.setString(3, userPassword); int insertedRow = insertPstmt.executeUpdate(); System.out.println(insertedRow + "개의 회원정보가 추가되었습니다."); insertPstmt.close(); sc.close(); } catch (SQLException e) { e.printStackTrace(); System.out.println("DB 연결 실패!"); } // CRUD // 회원가입 (C) // 회원 전체 확인 (R) // 특정 게시물 보기 (R) // 게시물 등록 (C) // 게시물 수정 (U) // 게시물 삭제 (D) // 연결 실패 if (conn != null) { try { conn.close(); System.out.println("DB 접속 종료"); } catch (SQLException e) { e.printStackTrace(); System.out.println("접속 종료 실패"); } } } } DB 연결 성공! 이름 입력 : 자유민 이메일 입력 : freedom@gmail.com 비밀번호 입력 : 1234 1개의 회원정보가 추가되었습니다. DB 접속 종료
Java
복사
회원 전체 확인
String selectAllSql = "SELECT * FROM users"; PreparedStatement userStmt = conn.prepareStatement(selectAllSql); ResultSet rs = userStmt.executeQuery(); while (rs.next()) { System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + " \t" + rs.getString("email") + "\t" + rs.getString("password")); } rs.close(); userStmt.close(); sc.close();
Java
복사
특정 사용자 확인
// 특정 게시물 보기 (R) System.out.print("사용자 아이디 번호 : "); int user_id = sc.nextInt(); String specSelectSql = "SELECT * " + " FROM users " + " WHERE id = ?"; PreparedStatement specUserStmt = conn.prepareStatement(specSelectSql); specUserStmt.setInt(1, user_id); ResultSet rs = specUserStmt.executeQuery(); if (rs.next()) { System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + " \t" + rs.getString("email") + "\t" + rs.getString("password")); } else { System.out.println("없는 사용자입니다."); } 사용자 아이디 번호 : 6 6 자유민 freedom@gmail.com 1234 DB 접속 종료
Java
복사