
| Products | 설명 |
|---|---|
| MySQL Server 8.0.25 - X64 | DBMS |
| MySQL Workbench 8.0.25 - X64 | DB 관리 및 개발을 위한 Client Tool |
| Connector/J 8.0.25 - X86 | JDBC Driver |


스키마를 우클릭해 set as default schema를 선택
⏬ 사용자 정보가 저장된 users 테이블
create table users (
userid varchar(50) primary key,
username varchar(50) not null,
userpassword varchar(50) not null,
userage numeric(3) not null,
useremail varchar(50) not null
);
⏬ 게시물 정보가 저장된 boards 테이블
create table boards (
bno int primary key auto_increment,
btitle varchar(100) not null,
bcontent longtext not null,
bwriter varchar(50) not null,
bdate datetime default now(),
bfilename varchar(50) null,
bfiledata longblob null
);
⏬ 계좌 정보가 저장될 accounts 테이블
create table accounts (
ano varchar(20) primary key,
owner varchar(20) not null,
balance numeric not null
);
insert into accounts (ano, owner, balance)
values ('111-111-1111', '하여름', 1000000);
insert into accounts (ano, owner, balance)
values ('222-222-2222', '한겨울', 0);
C:\Program Files (x86)\MySQL\Connector J 8.0import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/javapractice",
"java",
"mysql"
);
System.out.println("연결 성공");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
//연결 끊기
conn.close();
System.out.println("연결 끊기");
} catch (SQLException e) {}
}
}
}
}
➕ jdk 1.6부터는 getConnection 호출할 때 드라이버가 자동으로 로드되어 Class.forName 작성을 안 해도 된다

⚠️ "jdbc:mysql://localhost:3306/javapractice" → "jdbc:mysql://ip주소:포트/DB명"
DB명이라는 것에 조심하자!
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/javapractice",
"java",
"mysql"
);
//매개변수화된 SQL 문 작성
String sql = "" +
"INSERT INTO users (userid, username, userpassword, userage, useremail) " +
"VALUES (?, ?, ?, ?, ?)";
//PreparedStatement 얻기 및 값 지정
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "winter");
pstmt.setString(2, "한겨울");
pstmt.setString(3, "12345");
pstmt.setInt(4, 25);
pstmt.setString(5, "winter@mycompany.com");
//SQL 문 실행
int rows = pstmt.executeUpdate();
System.out.println("저장된 행 수: " + rows);
//PreparedStatement 닫기
pstmt.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
//연결 끊기
conn.close();
} catch (SQLException e) {}
}
}
}
}


import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/javapractice",
"java",
"mysql"
);
//매개변수화된 SQL 문 작성
String sql = new StringBuilder()
.append("UPDATE boards SET ")
.append("btitle= ?, ")
.append("bcontent= ?, ")
.append("bfilename= ?, ")
.append("bfiledata= ? ")
.append("WHERE bno= ?")
.toString();
//PreparedStatement 얻기 및 값 지정
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "눈사람");
pstmt.setString(2, "눈으로 만든 사람");
pstmt.setString(3, "snowman.jpg");
pstmt.setBlob(4, new FileInputStream("src/ch20/mysql/sec07/snowman.jpg"));
pstmt.setInt(5, 3); //boards 테이블에 있는 게시물 번호(bno) 지정
//SQL 문 실행
int rows = pstmt.executeUpdate();
System.out.println("수정된 행 수: " + rows);
//PreparedStatement 닫기
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
//연결 끊기
conn.close();
} catch (SQLException e) {
}
}
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/thisisjava",
"java",
"mysql"
);
//매개변수화된 SQL 문 작성
String sql = "DELETE FROM boards WHERE bwriter= ?";
//PreparedStatement 얻기 및 값 지정
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "winter");
//SQL 문 실행
int rows = pstmt.executeUpdate();
System.out.println("삭제된 행 수: " + rows);
//PreparedStatement 닫기
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
//연결 끊기
conn.close();
} catch (SQLException e) {}
}
}
}
}
만약 SELECT 문에 연산식이나 함수 호출이 포함되어 있다면 컬럼 이름 대신에 컬럼 순번으로 읽어
야 한다
String userId = rs.getString("userid");String userId = rs.getString(1);users 테이블의 한 개의 행(사용자)을 저장할 User 클래스
import lombok.Data;
@Data //Constructor, Getter, Setter, hashCode(), equals(), toString() 자동 생성
public class User {
private String userId;
private String userName;
private String userPassword;
private int userAge;
private String userEmail;
}
users 테이블에서 userid가 winter인 사용자 정보를 가져오는 코드
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/thisisjava",
"java",
"mysql"
);
//매개변수화된 SQL 문 작성
String sql = "" +
"SELECT userid, username, userpassword, userage, useremail " +
"FROM users " +
"WHERE userid= ?";
//PreparedStatement 얻기 및 값 지정
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "winter");
//SQL 문 실행 후, ResultSet을 통해 데이터 읽기
ResultSet rs = pstmt.executeQuery();
if(rs.next()) { //1개의 데이터 행을 가져왔을 경우
User user = new User();
user.setUserId(rs.getString("userid"));
user.setUserName(rs.getString("username"));
user.setUserPassword(rs.getString("userpassword"));
user.setUserAge(rs.getInt(4)); //컬럼 순번을 이용
user.setUserEmail(rs.getString(5)); //컬럼 순번을 이용
System.out.println(user);
} else { //데이터 행을 가져오지 않았을 경우
System.out.println("사용자 아이디가 존재하지 않음");
}
rs.close();
//PreparedStatement 닫기
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
//연결 끊기
conn.close();
} catch (SQLException e) {}
}
}
}
}
boards 테이블의 1개 행(게시물)을 저장할 Board 클래스
import java.sql.Blob;
import java.util.Date;
import lombok.Data;
@Data //Constructor, Getter, Setter, hashCode(), equals(), toString() 자동 생성
public class Board {
private int bno;
private String btitle;
private String bcontent;
private String bwriter;
private Date bdate;
private String bfilename;
private Blob bfiledata;
}
boards 테이블에서 bwriter가 winter인 게시물 정보를 가져오는 코드
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BoardSelectExample {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/thisisjava",
"java",
"mysql"
);
//매개변수화된 SQL 문 작성
String sql = "" +
"SELECT bno, btitle, bcontent, bwriter, bdate, bfilename, bfiledata " +
"FROM boards " +
"WHERE bwriter= ?";
//PreparedStatement 얻기 및 값 지정
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "winter");
//SQL 문 실행 후, ResultSet을 통해 데이터 읽기
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
//데이터 행을 읽고 Board 객체 생성
Board board = new Board();
board.setBno(rs.getInt("bno"));
board.setBtitle(rs.getString("btitle"));
board.setBcontent(rs.getString("bcontent"));
board.setBwriter(rs.getString("bwriter"));
board.setBdate(rs.getDate("bdate"));
board.setBfilename(rs.getString("bfilename"));
board.setBfiledata(rs.getBlob("bfiledata"));
//콘솔에 출력
System.out.println(board);
//파일로 저장
Blob blob = board.getBfiledata();
if(blob != null) {
InputStream is = blob.getBinaryStream();
Appendix
OutputStream os = new FileOutputStream("C:/Temp/" +
board.getBfilename());
is.transferTo(os);
os.flush();
os.close();
is.close();
}
}
rs.close();
//PreparedStatement 닫기
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
try {
//연결 끊기
conn.close();
} catch (SQLException e) {}
}
}
}
}
⚠️ JDBC에서는 INSERT, UPDATE, DELETE 문을 실행할 때마다 자동 커밋이 일어난다. 이 기능은
계좌 이체와 같이 두 가지 UPDATE 문을 실행할 때 문제가 된다. 출금 작업이 성공되면 바로 커밋
이 되기 때문에 입금 작업의 성공 여부와 상관없이 출금 작업만 별도 처리된다.
따라서 JDBC에서 트랜잭션을 코드로 제어하려면 자동 커밋 기능을 꺼야 한다
→ 자동 커밋 설정 여부는 Connection의 setAutoCommit() 메소드로 설정
accounts 테이블에서 111-111-1111계좌에서 222-222-2222 계좌로 만 원을 이체하기 위한 트랜잭션 처리 코드
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionExample {
public static void main(String[] args) {
Connection conn = null;
try {
//JDBC Driver 등록
Class.forName("com.mysql.cj.jdbc.Driver");
//연결하기
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/thisisjava",
"java",
"mysql"
);
//트랜잭션 시작 ----------------------------------------------------
//자동 커밋 기능 끄기
conn.setAutoCommit(false);
//출금 작업
String sql1 = "UPDATE accounts SET balance=balance-? WHERE ano= ?";
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
pstmt1.setInt(1, 10000);
pstmt1.setString(2, "111-111-1111");
int rows1 = pstmt1.executeUpdate();
if (rows1 == 0)throw new Exception("출금되지 않았음");
pstmt1.close();
//입금 작업
String sql2 = "UPDATE accounts SET balance=balance+? WHERE ano= ?";
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
pstmt2.setInt(1, 10000);
pstmt2.setString(2, "222-222-2222");
int rows2 = pstmt2.executeUpdate();
if (rows2 == 0)throw new Exception("입금되지 않았음");
pstmt2.close();
//수동 커밋 -> 모두 성공 처리
conn.commit();
System.out.println("계좌 이체 성공");
//트랜잭션 종료 ----------------------------------------------------
} catch (Exception e) {
try {
//수동 롤백 -> 모두 실패 처리
conn.rollback();
} catch (SQLException e1) {
}
System.out.println("계좌 이체 실패");
e.printStackTrace();
} finally {
if (conn != null) {
try {
//원래대로 자동 커밋 기능 켜기
conn.setAutoCommit(true);
//연결 끊기
conn.close();
} catch (SQLException e) {
}
}
}
}
}
➕ 커넥션 풀(Connection Pool)
다수의 클라이언트 요청을 처리하는 서버 프로그램은 대부분 커넥션 풀을 사용
생성된 Connection을 재사용할 수 있기에 DB 연결시간을 줄일 수 있고, 전체 Connnection을 수를 관리할 수도 있다
불특정 다수의 클라이언트 요청을 처리하는 서버 프로그램에서는 필수 기능 중 하나
이것이 자바다(신용권, 임경균 지음)