2023.09.06
Day18 네 줄 요약
- DBConnection( ) 클래스의 DBConnect( ) 메소드를 통해 DB 접속
- SQL 관련 객체들은 반드시 try-catch로 감싸야 함 (auto surround 기능 제공)
- 1) INSERT, 2) UPDATE, 3) DELETE의 경우 : int 타입의 변수(여기서는 'rseult')에 숫자를 받아 저장한 후 0보다 큰지 판별
- 4) SELECT의 경우 : ResultSet 객체(여기서는 'rs')에 쿼리문의 결과를 받아 저장한 후 rs.get 메소드로 값 저장
Oracle DB 접속을 위한 DBConnection 클래스 생성
DBConnect() 메소드의 type은 'Connection'이기 때문에 리턴 값의 type또한 Connection이다.
source code
package JDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
// Java-OracleDB 연결 매소드 DBConnect()
public static Connection DBConnect() { // static 메소드로 생성하면 객체 생성과정 생략 가능
Connection con = null; // static 메소드 호출은 클래스명으로 접근
String user = "ICIA";
String pw = "1111";
String url = "jdbc:oracle:thin:@localhost:1521:xe";
try {
// ojdbc8.jar 파일을 현재 프로젝트에 적용
Class.forName("oracle.jdbc.driver.OracleDriver");
// Java는 DriverManager 인터페이스를 통해 DB에 접속
con = DriverManager.getConnection(url, user, pw);
System.out.println("DB 접속 성공!");
} catch (ClassNotFoundException ce) {
// ojdbc8.jar 파일이 존재하지 않을 경우(오라클 드라이버를 찾지 못 할 경우) 오류가 발생한 경로를 찾아줌
ce.printStackTrace();
System.out.println("DB 접속 실패...드라이버 로딩 실패...");
} catch (SQLException se) {
// 오라클 계정정보(user, pw, url) 중 하나라도 틀린 경우
se.printStackTrace();
System.out.println("DB 접속 실패...DB 접속 정보 오류!");
}
return con;
}
}
JDBC
" JDBC(Java DataBase Connectivity)는 Java SE 에디션과 함께 패키지된
API(Application Program Interface)로, Java 애플리케이션을
RDBMS(Relational DataBase Management System, 관계형 데이터베이스 관리 시스템)에
연결하는 프로세스를 표준화하고 단순화할 수 있도록 해줍니다. "
https://www.theserverside.com/definition/Java-Database-Connectivity-JDBC
JDBC 구성 요소
JDBC API는 데이터베이스에 대한 연결을 나타내고 SQL 쿼리를 데이터베이스에 보내는 기능을 제공하며 Java 개발자가 관계형 데이터베이스 상호 작용의 결과를 처리하는 데 도움을 주는 여러 인터페이스와 클래스로 구성됩니다.
java.sql.Connection | Java 프로그램에서 외부 DB 시스템으로의 연결을 나타냄 |
java.sql.Statement | 연결된 DB에서 SQL 문을 실행하는 데 사용 |
java.sql.PreparedStatement | 사전 컴파일된 SQL 문을 연결된 DB에서 실행하는 데 사용 |
java.sql.ResultSet | SQL 문이 처리된 후 DB에서 반환된 결과를 나타냄 |
java.sql.Blob | 이미지나 비디오와 같은 large binary object를 포함하는 DB 파일을 나타냄 |
SQL 객체생성
쿼리문의 작성과 결과값 반환에 관련된 객체들은 항상 try-catch로 감싸야 함
해당 객체들은 SQL 관련 클래스(ex. BankSQL, StudentSQL, ...)에서 선언하고 메소드 안에서 사용
1) Connection con;
// 1. DB 접속 메소드
public void connect() {
/* DBConnect() 메소드가 static이 아닐 경우,
DBConnection() 클래스 객체 먼저 생성해야 함
DBConnection conn = new DBConnection();
con = conn.DBConnect();
*/
con = DBConnection.DBConnect();
}
2) PreparedStatement pstmt;
'?(물음표 기호)'를 통해 쿼리문에 매개변수로 받은 값을 저장
물음표 개수만큼 index가 자동으로 1부터 numbering됨
- pstmt = con.prepareStatement(sql)
: String sql = "UPDATE ...."; 와 같은 쿼리문 문자열 sql을 pstmt에 저장
- pstmt.executeUpdate()
: DB에서 1) INSERT, 2) UPDATE, 3) DELETE 기능을 수행 후, update 완료된 행의 개수를 int type 으로 반환
- pstmt.executeQuery()
: DB에서 4) SELECT 기능을 수행 후 조회된 컬럼들의 값을 반환 (rs 객체와 짝꿍)
// 4-2. 입금 메소드
public void deposit(String cAccount, int money) {
String sql = "UPDATE BANKCLIENT SET BALANCE = BALANCE + ? WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, money);
pstmt.setString(2, cAccount);
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.println("입금 성공!");
} else {
System.out.println("입금 실패...");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
3) ResultSet rs;
pstmt.executeQuery() 와 짝꿍으로, 조회한 컬럼의 데이터를 반환
- rs.next() : 조회된 컬럼의 값이 있으면 true, 없으면 false 리턴
- rs.get___(index) : ___ = 받아오는 값의 type, index = 컬럼의 순서를 입력
// 5-1. 잔액 조회 메소드
public int getBalance(String cAccount) {
int balance = 0;
String sql = "SELECT BALANCE FROM BANKCLIENT WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setString(1, cAccount);
rs = pstmt.executeQuery();
while (rs.next()) {
balance = rs.getInt(1);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return balance;
}
예제 (뱅킹프로그램 Bank)
source code
* 코드블럭의 class 순서는 다음과 같고, IntelliJ(인텔리제이) IDE에서 작성 됨
1) DBConnection( ) : DB 연결을 위한 클래스
2) BankClient( ) : 회원정보가 담긴 객체(여기선 'client')를 저장하기 위한 클래스
3) BankSQL( ) : SQL 관련 객체를 정의하고 main에서 사용할 쿼리문 메소드가 담긴 클래스
4) BankMain( ) : Bank project의 main 클래스
package Bank;
// [1] DBConnection
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
public static Connection DBConnect(){
Connection con = null;
String user = "ICIA";
String password = "1111";
String url = "jdbc:oracle:thin:@localhost:1521:xe";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(url, user, password);
System.out.println("DB 접속 성공!");
} catch (ClassNotFoundException | SQLException e) {
System.out.println("DB 접속 실패...");
throw new RuntimeException(e);
}
return con;
}
}
// [2] BankClient
public class BankClient {
// 1. 필드
private int cNum;
private String cName;
private String cAccount;
private int Balance;
// 2. 생성자 : default
// 3. 메소드
public int getcNum() {
return cNum;
}
public void setcNum(int cNum) {
this.cNum = cNum;
}
public String getcName() {
return cName;
}
public void setcName(String cName) {
this.cName = cName;
}
public String getcAccount() {
return cAccount;
}
public void setcAccount(String cAccount) {
this.cAccount = cAccount;
}
public int getBalance() {
return Balance;
}
public void setBalance(int Balance) {
this.Balance = Balance;
}
@Override
// 사용은 하지 않음
public String toString() {
return "BankClient{" +
"cNum=" + cNum +
", cName='" + cName + '\'' +
", cAccount='" + cAccount + '\'' +
", balacnce=" + Balance +
'}';
}
}
// [3] BankSQL
import java.sql.*; // sql 관련 객체 선언에 필요한 모든 패키지들을 한 번에 import
public class BankSQL {
Connection con;
PreparedStatement pstmt;
Statement stmt;
ResultSet rs;
// 1. DB 접속 메소드
public void connect() {
/* DBConnect() 메소드가 static이 아닐 경우,
DBConnection() 클래스 객체 먼저 생성해야 함
DBConnection conn = new DBConnection();
con = conn.DBConnect();
*/
con = DBConnection.DBConnect();
}
// 2. DB 해제 메소드
public void conClose() {
try {
con.close();
System.out.println("DB 접속 해제!");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 3-1. 고객번호 생성
public int clientNum() {
int cNum = 0;
String sql = "SELECT MAX(CNUM) FROM BANKCLIENT";
try {
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
if (rs.next()) {
cNum = rs.getInt(1) + 1;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return cNum;
}
// 3-2. 계좌번호 생성
public String clientAccount() {
String newAccount = "110-";
for (int i = 0; i < 3; i++) {
int account1 = (int)((Math.random() * 9) + 1);
newAccount += account1;
}
newAccount += "-";
for (int i = 0; i < 6; i++) {
int account2 = (int)((Math.random() * 9) + 1);
newAccount += account2;
}
return newAccount;
}
// 3-3. DB에 정보 저장
public void clientJoin(BankClient client) {
String sql = "INSERT INTO BANKCLIENT VALUES(?,?,?,?)";
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, client.getcNum());
pstmt.setString(2, client.getcName());
pstmt.setString(3, client.getcAccount());
pstmt.setInt(4, client.getBalance());
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.printf("%s 님, 계좌생성 완료!\n계좌번호 : %s\n계좌잔액 : %,d원", client.getcName(), client.getcAccount(), client.getBalance());
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 4-1. 계좌 유무 확인 메소드
public boolean checkAccount(String cAccount) {
boolean check = false;
String sql = "SELECT * FROM BANKCLIENT WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setString(1, cAccount);
rs = pstmt.executeQuery();
if (rs.next()) {
check = true;
} else {
System.out.println("조회할 수 없는 계좌입니다...");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return check;
}
// 4-2. 입금 메소드
public void deposit(String cAccount, int money) {
String sql = "UPDATE BANKCLIENT SET BALANCE = BALANCE + ? WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, money);
pstmt.setString(2, cAccount);
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.println("입금 성공!");
} else {
System.out.println("입금 실패...");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 5-1. 잔액 조회 메소드
public int getBalance(String cAccount) {
int balance = 0;
String sql = "SELECT BALANCE FROM BANKCLIENT WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setString(1, cAccount);
rs = pstmt.executeQuery();
while (rs.next()) {
balance = rs.getInt(1);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return balance;
}
// 5-2. 출금 메소드
public void withdraw(String cAccount, int money) {
String sql = "UPDATE BANKCLIENT SET BALANCE = BALANCE - ? WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, money);
pstmt.setString(2, cAccount);
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.println("출금 성공!");
} else {
System.out.println("출금 실패...");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 6. 송금 메소드
public void transferMoney(String sendAccount, String receiveAccount, int money) {
String sql1 = "UPDATE BANKCLIENT SET BALANCE = BALANCE - ? WHERE CACCOUNT = ?";
String sql2 = "UPDATE BANKCLIENT SET BALANCE = BALANCE + ? WHERE CACCOUNT = ?";
try {
pstmt = con.prepareStatement(sql1);
pstmt.setInt(1, money);
pstmt.setString(2, sendAccount);
pstmt.executeUpdate();
pstmt = con.prepareStatement(sql2);
pstmt.setInt(1, money);
pstmt.setString(2, receiveAccount);
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.println("송금 성공!");
} else {
System.out.println("송금 실패...");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 7. 목록 조회 메소드
public void selectClient() {
String sql = "SELECT * FROM BANKCLIENT";
try {
System.out.println("No.\t\tName\t\tAccount\t\t\t\tBalance");
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
System.out.printf("%d\t\t%s\t\t%s\t\t%,d원\n", rs.getInt(1), rs.getString(2), rs.getString(3), rs.getInt(4));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
// [4] BankMain
import java.util.Scanner;
public class BankMain {
public static void main(String[] args) {
BankClient client = new BankClient();
BankSQL sql = new BankSQL();
Scanner sc = new Scanner(System.in);
boolean run = true;
while (run) {
System.out.println("=====================라즈베리은행=====================");
System.out.println("[1]DB접속 [2]DB해제 [3]계좌생성 [4]입금");
System.out.println("[5]출금 [6]송금 [7]조회 [8]종료");
System.out.println("=====================================================");
System.out.print("메뉴선택 > ");
String menu = sc.next();
switch (menu) {
case "1": // DB 접속
sql.connect();
break;
case "2": // DB 해제
sql.conClose();
break;
case "3": // 계좌생성
client.setcNum(sql.clientNum());
client.setcAccount(sql.clientAccount());
System.out.print("이름 > ");
client.setcName(sc.next());
System.out.print("초기잔액 > ");
client.setBalance(sc.nextInt());
sql.clientJoin(client);
break;
case "4": // 입금
System.out.print("입금할 계좌 > ");
String inputAccount = sc.next();
boolean check = sql.checkAccount(inputAccount);
if (check) {
System.out.print("입금 금액 > ");
int money = sc.nextInt();
sql.deposit(inputAccount, money);
}
break;
case "5": // 출금
System.out.print("출금할 계좌 > ");
inputAccount = sc.next();
check = sql.checkAccount(inputAccount);
if (check) {
System.out.print("출금 금액 > ");
int money = sc.nextInt();
if (sql.getBalance(inputAccount) < money) {
System.out.println("잔액이 부족합니다...");
} else {
sql.withdraw(inputAccount, money);
}
}
break;
case "6": // 송금
System.out.print("보내시는 분 계좌 > ");
String sendAccount = sc.next();
check = sql.checkAccount(sendAccount);
if (check) {
System.out.print("받으시는 분 계좌 > ");
String receiveAccount = sc.next();
if (sendAccount.equals(receiveAccount)) {
System.out.println("동일한 계좌로의 송금은 진행할 수 없습니다...");
} else {
boolean checkSA = sql.checkAccount(receiveAccount);
if (checkSA) {
System.out.print("보내실 금액 > ");
int money = sc.nextInt();
if (sql.getBalance(sendAccount) < money) {
System.out.println("잔액이 부족합니다...");
} else {
sql.transferMoney(sendAccount, receiveAccount, money);
}
}
}
}
break;
case "7": // 조회
sql.selectClient();
break;
case "8": // 종료
System.out.println("프로그램 종료...");
run = false;
break;
default:
System.out.println("1~8중에 입력하세요...");
break;
}
System.out.println();
}
}
}
Oracle DB
DROP TABLE BANKCLIENT;
CREATE TABLE BANKCLIENT(
CNUM NUMBER PRIMARY KEY,
CNAME NVARCHAR2(10),
CACCOUNT NVARCHAR2(20),
BALANCE NUMBER
);
COMMIT;
'Spring-Java > JDBC' 카테고리의 다른 글
Day22_Banking 예제 2 (0) | 2023.09.12 |
---|