데이터베이스 입출력
•
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
복사