JDBC
싱글톤 패턴으로
connection pool에서 DB에 연결된 연결 객체를 생성해 두었다가 갖다쓴다
HikariCP가 가장 성능이 좋음
https://hudi.blog/dbcp-and-hikaricp/
현업에서는 성능개선을 위해서 connection 객체를 미리 생성해서 사용하고 반환하는
pool 방식을 선택한다.
https://hudi.blog/dbcp-and-hikaricp/
spring 프로젝트 진행시 당연히 connection pool 방식 사용...
JDBC insert
package kr.or.kosa.utils;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/*
DML(insert, update, delete)
JDBC API 작업
1. 결과 집합이 없다.(resultSet 필요없다.)
2. 반영결과 (return 행의 수) >>update 5건 반영 > return 5
ex)
update emp set sal=0; > 성공 > return 14 > 사원수 14명
update emp set sal = 1000 where empno=99999; > return 0
우리가 개발 툴에서 (DML) 반드시 해야하는 작업
KEY POINT
1. SQL 툴 작업 : commit 또는 rollback 강제
2. JDBC API 사용해서 java코드를 DML >> default >>autocommit(자바에서 지우면 다 날아감)>> 실반영
3. 필요에 따라서 autocommit 옵션을 제어 가능 >>false>> java 반드시 >> commit 과 rollback을 처리해야한다.
실습 SQL
create table dmlemp
as
select * from emp;
select * from dmlemp;
alter table dmlemp add constraint pk_dmlemp_empno primary key(empno);
select * from user_constraints where table_name='DMLEMP';
* */
public class Ex04_Oracle_DML_insert {
public static void main(String[] args) {
Statement stmt =null;
Connection conn = ConnectionHelper.getConnection("oracle");
try {
stmt = conn.createStatement();
//INSERT
int empno =0;
String ename ="0";
int deptno=0;
Scanner sc = new Scanner(System.in);
System.out.println("사번입력");
empno=Integer.parseInt(sc.nextLine());
System.out.println("이름입력");
ename = sc.nextLine();
System.out.println("부서입력");
deptno = Integer.parseInt(sc.nextLine());
//insert into dmlemp(empno,ename,deptno) values(100,'홍길동',10);
//실행될 sQL구문을 문자열로 조합(구시대적인 방식;)
String sql = "insert into dmlemp(empno, ename,deptno)";
sql+="values("+empno+",'"+ename+"',"+deptno+")";
System.out.println(sql);
//현재 (preparestatement)
// "insert into dmlemp(empno, ename, deptno) values(?,?,?)"
int row = stmt.executeUpdate(sql);
//이 하나가 insert, update delete를 모두 수행한다.
//executeUpdate에서 예외가발생하ㅈ 읺으면
if(row>0) {
System.out.println("반영된 행의 수 : "+row);
}
else {
System.out.println("예외가발생한 것이 아ㅣㄴ고 반영된 행이 없다.");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
//excuteUpdate 예외가 바생하면 이리로 이동
e.printStackTrace();
}finally {
//강제 수행 블럭
//자원해제하기
ConnectionHelper.close(stmt);
ConnectionHelper.close(conn);
}
}
}
JDBC UPDATE
package kr.or.kosa.utils;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/*
*
급여, 수당, 부서번호 입력받으세요
update dmlemp set sal=0 , comm=0 where deptno=10
"update dmlemp set sal=" + sal+","+comm="+comm+"where deptno=" +deptno
* */
public class Ex05_Oracle_DML_update {
public static void main(String[] args) {
Statement stmt =null;
Connection conn = ConnectionHelper.getConnection("oracle");
try {
stmt = conn.createStatement();
//INSERT
int sal =0;
int comm =0;
int deptno=0;
Scanner sc = new Scanner(System.in);
System.out.println("월급입력");
sal=Integer.parseInt(sc.nextLine());
System.out.println("보너스입력");
comm=Integer.parseInt(sc.nextLine());
System.out.println("부서입력");
deptno = Integer.parseInt(sc.nextLine());
//insert into dmlemp(empno,ename,deptno) values(100,'홍길동',10);
//실행될 sQL구문을 문자열로 조합(구시대적인 방식;)
String sql = "update dmlemp set sal=" + sal+","+"comm="+comm+"where deptno=" +deptno;
System.out.println(sql);
//현재 (preparestatement)
// "insert into dmlemp(empno, ename, deptno) values(?,?,?)"
int row = stmt.executeUpdate(sql);
//이 하나가 insert, update delete를 모두 수행한다.
//executeUpdate에서 예외가발생하ㅈ 읺으면
if(row>0) {
System.out.println("반영된 행의 수 : "+row);
}
else {
System.out.println("예외가발생한 것이 아ㅣㄴ고 반영된 행이 없다.");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
//excuteUpdate 예외가 바생하면 이리로 이동
e.printStackTrace();
}finally {
//강제 수행 블럭
//자원해제하기
ConnectionHelper.close(stmt);
ConnectionHelper.close(conn);
}
}
}
JDBC DELETE
package kr.or.kosa.utils;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/*
delete from dmlemp where empno=200;
"delete from dmlemp where empno="+empno;
* */
public class Ex06_Oracle_DML_delete {
public static void main(String[] args) {
Statement stmt =null;
Connection conn = ConnectionHelper.getConnection("oracle");
try {
stmt = conn.createStatement();
//INSERT
int empno =0;
int comm =0;
int deptno=0;
Scanner sc = new Scanner(System.in);
System.out.println("사번입력");
empno=Integer.parseInt(sc.nextLine());
/*
* System.out.println("보너스입력"); comm=Integer.parseInt(sc.nextLine());
* System.out.println("부서입력"); deptno = Integer.parseInt(sc.nextLine());
*/
//insert into dmlemp(empno,ename,deptno) values(100,'홍길동',10);
//실행될 sQL구문을 문자열로 조합(구시대적인 방식;)
String sql = "delete from dmlemp where empno="+empno;
System.out.println(sql);
//현재 (preparestatement)
// "insert into dmlemp(empno, ename, deptno) values(?,?,?)"
int row = stmt.executeUpdate(sql);
//이 하나가 insert, update delete를 모두 수행한다.
//executeUpdate에서 예외가발생하ㅈ 읺으면
if(row>0) {
System.out.println("반영된 행의 수 : "+row);
}
else {
System.out.println("예외가발생한 것이 아니고 반영된 행이 없다.");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
//excuteUpdate 예외가 바생하면 이리로 이동
e.printStackTrace();
}finally {
//강제 수행 블럭
//자원해제하기
ConnectionHelper.close(stmt);
ConnectionHelper.close(conn);
}
}
}
JDBC PreparedStatement
? 기호를 사용해서 편리하게 파라미터를 전달하기 위함
미리 쿼리를 실행 시켜놓고 파라미터만 전달해서 실행한다.
package kr.or.kosa.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/*
PreparedStatement (준비된 명령 객체)
--미리 실행될 쿼리 문장을 DB 서버에 보내서 컴파일 시켜 놓고..
--추후에 필요한 parameter값만 전송해서 실행
-->select * from emp where empno=?
-->?에 해당하는 parameter 값 던지면 내가 던진 파라미터값으로 실행된다
Oracle 서버에게..
--> select empno, ename from emp where empno=7788 다른쿼리
--> select empno, ename from emp where Empno=7788 다른쿼리
--> select empno, ename from emp where Empno=8888 다른쿼리
이 둘이 같을까?
shared pool에 쿼리들을 모아두는데 위에 두개를 다르게 봐서
--> select * from emp where empno=? 오라클
--> 1000 or 7788 같은 쿼리야 ( 같은 실행계획)
보안도 좋고 성능도 좋아
Statement는 정형화된 쿼리에는 사용 좋음 고정된 쿼리
PreparedStatement
장점)
1. Statement객체에 비해서 반복적인(parameter) 있는 sQL 사용시 성능상 빠르다(검색)
2. parameter 처리에 있어서 타입을 인정 (? 타입을 쉽게 처리)
단점)
1. SQL문 마다 preparedStatement 객체를 새로만들어야한다
* */
public class Ex07_Oracle_PrepareStatement {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs =null;
try {
conn = ConnectionHelper.getConnection("oracle");
// conn.createStatement();
String sql="select empno, ename from emp where deptno=?";
pstmt = conn.prepareStatement(sql); // 오라클 서버에게 문장을 보내서 컴파일시켜 놓고 대기
pstmt.setInt(1, 30);//첫번째는 ?의 순서, 두번째는 들어갈 값
//insert into emp(empno,ename,sal, comm) values(?,?,?,?);
// pstmt.setInt(1, 30);
// pstmt.setInt(2, 30);
// pstmt.setInt(3, 30);
// pstmt.setInt(4, 30);
//실행
rs = pstmt.executeQuery();
//공식같은 로직
//select > 1건, 1건이상, 없다
if(rs.next()) {//true : 한건은 있다.
do {
System.out.println(rs.getInt(1)+"/"+rs.getString(2));
}while(rs.next());//false : next()가 없을때
}else {
System.out.println("데이터가 없습니다.");
}
}catch(Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}finally {
ConnectionHelper.close(rs);
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
}
}
JDBC Transaction
package kr.or.kosa.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
create table trans_A(
num number,
name varchar2(20)
);
create table trans_B(
num number constraint pk_trans_B_num primary key,
name varchar2(20)
);
JDBC > dml(insert, update, delete) > default > auto commit >실반영
JDBC > dml >개발자 > commit, rollback 강제 > 옵션 auto commit > false
.업무
은행 ( A계좌에서 B계좌로 이체할때) > 하나의 논리적인 단위로 묶지 않으면 A에서 이체되고 B에 입금이 안되는경우 발생가능
>transaction을만들어야한다.> 둘다 성공, 실패! 극단적인 경우로 짜야함
쇼핑결제
* */
public class Ex07_Oracle_Transaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
PreparedStatement pstmt2 = null;
conn = ConnectionHelper.getConnection("oracle");
String sql ="insert into trans_A(num,name) values(100,'A')";
String sql2 ="insert into trans_B(num,name) values(100,'B')";
try {
//둘다 성공 아니면 둘다 실패(하나의 논리적 단위)
conn.setAutoCommit(false);//개발자가 commit과 rollback을 강제할수 있다 auto commit off
//begin tran
pstmt = conn.prepareStatement(sql);
pstmt.executeQuery();
pstmt2 = conn.prepareStatement(sql2);
pstmt2.executeQuery();
//end tran
//실행이 여기까지 오면 둘다 성공으로 한다
//commit!
conn.commit();//KEY POINT
}catch(Exception e) {
//문제가 발생하면 transation실행을 되돌린다
System.out.println("문제 발생 :" +e.getMessage());
try {
conn.rollback();//둘다 취소.. 원점으로 돌아간다
} catch (Exception e1) {
System.out.println(e1.getMessage());
}
}finally {
ConnectionHelper.close(pstmt);
ConnectionHelper.close(pstmt2);
ConnectionHelper.close(conn);
}
}
}
데이터베이스에 존재하는 내용을 java에서 검색해서 갖다 쓸수 있으면 정말 좋겟네
단, 객체로 주고 받아야한다
DTO : Dept.java
DAO : DeptDao.java
DTO
package com.kosa.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/*
DB dept 테이블의 한개 데이터를 담는다
CREATE TABLE DEPT
(DEPTNO number,
DNAME VARCHAR2(14),
LOC VARCHAR2(13) );
getter() , setter()
toString()
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private int deptno;
private String dname;
private String loc;
}
DAO
package com.kosa.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.kosa.dto.Dept;
import com.kosa.utils.ConnectionHelper;
/*
1. Dept 테이블 전체 조회
2. Dept 조건 조회 where deptno=?
3. insert (번호 , 이름 , 지역)
4. update (이름, 지역) 조건 where deptno=?
5. delete (번호)
6. Like 검색 (부서이름 검색)
*/
public class DeptDao {
//1. 전체조회 >> select * from dept
//>> return multi row
public List<Dept> getDeptAllList(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//POINT
List<Dept> deptlist = new ArrayList<Dept>();
try {
conn = ConnectionHelper.getConnection("oracle");
String sql = "select deptno, dname, nvl(loc,'empty')as loc from dept";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
Dept dept = new Dept(); // 하나의 row 담기 위한 객체
dept.setDeptno(rs.getInt("deptno"));
dept.setDname(rs.getString("dname"));
dept.setLoc(rs.getString("loc"));
deptlist.add(dept); // 배열에 객체 담는 것
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
ConnectionHelper.close(rs);
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return deptlist;
}
//2. 조건조회 (deptno pk) >> select * from dept where deptno=?
//>> return singlerow
public Dept getDeptListByDeptNo(int deptno) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//POINT
Dept dept =null;
try {
conn = ConnectionHelper.getConnection("oracle");
String sql = "select deptno, dname, loc from dept where deptno=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, deptno);
rs = pstmt.executeQuery();
while (rs.next()) {
dept = new Dept(); // 하나의 row 담기 위한 객체
dept.setDeptno(rs.getInt("deptno"));
dept.setDname(rs.getString("dname"));
dept.setLoc(rs.getString("loc"));
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
ConnectionHelper.close(rs);
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return dept;
}
//3. 데이터 삽입 >> insert into dept(deptno,dname,loc) values(?,?,?)
//public int insertDept(int deptno , String dname, String loc) {}
public int insertDept(Dept dept) {
Connection conn = null;
PreparedStatement pstmt=null;
int rowcount = 0;
try {
conn = ConnectionHelper.getConnection("oracle");
String sql="insert into dept(deptno,dname,loc) values(?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, dept.getDeptno());
pstmt.setString(2, dept.getDname());
pstmt.setString(3, dept.getLoc());
rowcount = pstmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}finally {
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return rowcount;
}
//4. 데이터 수정 >> update dept set dname=? , loc=? where depno=?
public int updateDept(Dept dept) {
Connection conn = null;
PreparedStatement pstmt=null;
int rowcount = 0;
try {
conn = ConnectionHelper.getConnection("oracle");
String sql="update dept set dname=? , loc=? where deptno=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, dept.getDname());
pstmt.setString(2, dept.getLoc());
pstmt.setInt(3, dept.getDeptno());
rowcount = pstmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}finally {
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return rowcount;
}
//5. 데이터 삭제 >>delete from dept where deptno=?
public int deleteDept(int deptno) {
Connection conn = null;
PreparedStatement pstmt=null;
int rowcount = 0;
try {
conn = ConnectionHelper.getConnection("oracle");
String sql="delete from dept where deptno=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, deptno);
rowcount = pstmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}finally {
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return rowcount;
}
//필요에 따라서
//검색 Like ..
//여러개의 조건조회 ....
//6.
//문제 >> 부서이름을 LIKE 검색해서 해당하는 부서번호 , 부서이름 , 부서위치 를 반환하는
//함수를 만드세요
//query >> select deptno , dname , loc from dept where dname like '%SEOUL%'
//무식하게 표현하면 >> where dname like '%" + dname +"'%"
public List<Dept> getDeptAllListByDname(String dname){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//POINT
List<Dept> deptlist = new ArrayList<Dept>();
try {
conn = ConnectionHelper.getConnection("oracle");
String sql = "select deptno, dname, loc from dept where like ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "%" + dname + "%"); //like '%SEOUL%'
rs = pstmt.executeQuery();
while (rs.next()) {
Dept dept = new Dept(); // 하나의 row 담기 위한 객체
dept.setDeptno(rs.getInt("deptno"));
dept.setDname(rs.getString("dname"));
dept.setLoc(rs.getString("loc"));
deptlist.add(dept); // 배열에 객체 담는 것
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
ConnectionHelper.close(rs);
ConnectionHelper.close(pstmt);
ConnectionHelper.close(conn);
}
return deptlist;
}
//아래처럼 함수를 만드시면
//close() 하지 않아도 됩니다
public void functionScope() throws SQLException {
try(Connection conn = ConnectionHelper.getConnection("oracle");) {
try (PreparedStatement pstmt = conn.prepareStatement("select * from emp");)
{
ResultSet rs = pstmt.executeQuery();
}catch (Exception e) {
e.printStackTrace();
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
출력을 하기 위한 Program.java
import java.util.List;
import com.kosa.dao.DeptDao;
import com.kosa.dto.Dept;
/*
MVC 패턴 (너 잘하는 것만 해라)
Model : 데이터 >> dto(vo) , dao(CURD)함수 , service >> java(pojo)
View : 현재 cmd(console) , WEB(html , jsp view template)
Controller : 웹을 기준 (jsp , servlet) >> request , response 객체 >> cmd(console)
*/
public class Program {
public static void main(String[] args) {
//main 함수 (View) 영역
//DAO객체 요청
DeptDao dao = new DeptDao(); //6개의 함수
System.out.println("[전체조회]*******");
List<Dept> deptlist =dao.getDeptAllList();
//화면구성
if(deptlist != null) {
deptPrint(deptlist);
}
//조건조회
System.out.println("[조건조회]*******");
Dept dept =dao.getDeptListByDeptNo(10);
if(dept != null) {
deptPrint(dept);
}else {
//.....
}
System.out.println("[데이터 삽입]*******");
Dept insertdept = new Dept();
insertdept.setDeptno(100);
insertdept.setDname("IT");
insertdept.setLoc("SEOUL");
int row = dao.insertDept(insertdept);
if(row > 0) {
System.out.println("insert rowcount : " + row);
}
System.out.println("[방금전 insert 데이터 전체조회]*******");
deptlist =dao.getDeptAllList();
//화면구성
if(deptlist != null) {
deptPrint(deptlist);
}
System.out.println("[방금전 insert 데이터 수정하기]*******");
Dept updatedept = new Dept();
updatedept.setDeptno(100);
updatedept.setDname("IT_UP");
updatedept.setLoc("SEOUL_UP");
row = dao.updateDept(updatedept);
if(row > 0) {
System.out.println("update rowcount : " + row);
}
System.out.println("[방금전 update 데이터 전체조회]*******");
deptlist =dao.getDeptAllList();
//화면구성
if(deptlist != null) {
deptPrint(deptlist);
}
System.out.println("[방금전 update 데이터 삭제하기]*******");
row = dao.deleteDept(100);
if(row > 0) {
System.out.println("delete rowcount : " + row);
}
System.out.println("[방금전 delete 데이터 전체조회]*******");
deptlist =dao.getDeptAllList();
//화면구성
if(deptlist != null) {
deptPrint(deptlist);
}
}
public static void deptPrint(Dept dept) {
System.out.println(dept.toString());
}
public static void deptPrint(List<Dept> list) {
for(Dept data : list) {
System.out.println(data.toString());
}
}
}
builder 패턴
https://pamyferret.tistory.com/67
//조건조회
System.out.println("[조건조회]*******");
Dept dept =dao.getDeptListByDeptNo(10);
if(dept != null) {
deptPrint(dept);
}else {
//.....
}
System.out.println("[데이터 삽입]*******");
//Dept insertdept = new Dept();
Dept insertdept =Dept.builder().deptno(100).dname("IT").loc("SEOUL").build();
//insertdept.setDeptno(100);
//insertdept.setDname("IT");
//insertdept.setLoc("SEOUL");
int row = dao.insertDept(insertdept);
if(row > 0) {
System.out.println("insert rowcount : " + row);
}
몽크라는곳에서 프리랜서??
'오라클 데이터베이스' 카테고리의 다른 글
SQL 9일차(0720) (0) | 2023.07.20 |
---|---|
SQL8일차(0719) (0) | 2023.07.19 |
sQL 6일차(0717) (0) | 2023.07.17 |
SQL 2일차(0711) (0) | 2023.07.16 |
sql 5일차(0714) (0) | 2023.07.14 |