JDBC / 오라클 연동, Statement, PreparedStatement

Cheol·2023년 6월 19일

edu day 25, 26, 27, 28

추가 / 수정

23/06/19 - JDBC 기본 개발 순서 && 실행
23/06/20 - DML 코드 구현 / DAO,DTO 클래스 분류
23/06/21 - SERVICE 클래스 분류 / 트랜잭션 다루기
23/06/22 - 트랜잭션 다루기 수정 / 추가



JDBC (Java DataBase Connectivity)

java환경과 db환경을 커넥션하는 것으로 eclipse에서 Oracle SQL과 연동하는 작업을 할 것이다.

앞으로 배울 내용 총정리

  1. 오라클 연동 : 오라클용 api : 프로젝트마다 ojbc6g.jar 라이브러리 추가
  2. 오라클 연동시 sql 작성, 실행, 결과 확인
    2-1. Statement객체 이용 (사용 안함 : sql 작성 어려움)
    2-2. PreparedStatement객체 이용 (사용안함)
    2-3. Mybatis 기술 이용 : 최종 목표, 그러나 초반 환경설정이 매우 까다롭다.

ojbdb: db연동을 위한 함수가 다 들어있다.


❗❗JDBC를 구현하는 기본적인 프로그램 개발 순서

  1. 오라클 데이터베이스 연동을 위한 4가지 정보 저장
String driver = "oracle.jdbc.driver.OracleDriver" ;
String url = "jdbc:oracle:thin:@localhost:1521:orcl";
String userid = "scott";
String passwd = "tiger";
  1. 드라이버 로딩
Class.forName(driver);
  1. Connection 맺기
Connection con = DriverManager.getConnection(url, userid, passwd)
  1. SQL문 작성(주의❗ : ;(세미콜론)은 사용 안함
String query = "SELECT deptno, dname, loc, FROM dept";
String query = "DELETE FROM dept WHERE deptno = 40";
  1. PreparedStatement 생성
PerparedStatement pstmt = con.prepareStatment(query);
  1. SQL문 전송 및 결과값 얻기
  • DML 요청(INSERT, DELETE, UPDATE)인 경우 코드
int n = pstmt.executeUpdate(); 
  • SELECT 요청
ResultSet rs = pstmt.executeQuery();
re.next() 및 re.getInt(컬럼명), rs.getString(컬럼명) 이용하여 데이터 추출
  1. 자원 반납 (사용했던 자원 역순)
rs.close()	//ResultSet을 사용한 경우
stmt.close();
con.close();

😁실행

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class StatementTest {

	public static void main(String[] args) {
		//1. db접속용 4가지 정보
		//로딩할 드라이버 이름
		String driver = "oracle.jdbc.driver.OracleDriver";
		//드라이버 이용 접속할 오라클 서버 주소
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		//스키마 명
		String userid = "scott";
		String passwd = "tiger";

		Connection con = null;	//접속객체 => 접속후 Statement 생성
		Statement stmt = null;	//sql을 실행할 객체
		//select : executeQuery(sql), dml : executeUpdate(sql)
		ResultSet rs = null;	//select 결과를 저장할 객체
		
		try {
			//2. 드라이버 로딩
			Class.forName(driver);
			System.out.println("드라이버 로딩성공");
			
			//3. DB에 connection 연결
			con = DriverManager.getConnection(url, userid, passwd);
			System.out.println(con);
			
			//4. Statement 생성, sql 작성, sql 실행
			stmt = con.createStatement();	//Statement 객체 생성
//			String sql = "select * from dept;";	// ;(세미콜론) 있으면 안됨.
			String sql = "select * from dept";	// ;(세미콜론) 제거
			
			//5. 실행 결과 받기
			rs = stmt.executeQuery(sql);	//sql 실행
			//6. ResultSet결과 출력
			while (rs.next()) {	//하나의 레코드 읽기, 컬럼별 변수에 저장
				int deptno = rs.getInt("deptno");	//컬럼명
				String dname = rs.getString("dname");	//컬럼명
				String loc = rs.getString(3);	//Index 사용
				System.out.println(deptno+"\t"+ dname +"\t" + loc);
			}
			System.out.println("결과 출력 끝");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			//7. 사용 자원 반납 (사용했던 자원의 역순으로)
			try {
				if(rs != null)rs.close();
				if(stmt != null)stmt.close();
				if(con != null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		

	}

}

여기서 큰 틀은 변하지 않으니 외워버리자❗❗

  • 😋SELECT 예제
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCTest {

	public static void main(String[] args) {

		String driver = "oracle.jdbc.driver.OracleDriver";
        String url = "jdbc:oracle:thin:@localhost:1521:xe";
        String userid = "scott";
        String passwd = "tiger";
        
        Connection con = null;
        PreparedStatement pstmt =null;	
        //PreparedStatement는 sql문에 ?를 사용하여 값을 지정할 수 있다.
        ResultSet rs = null;
        try {
			Class.forName(driver);
			System.out.println("호출 성공");
			con = DriverManager.getConnection(url, userid, passwd);
        	String sql = "select deptno x, dname, loc from dept where deptno = ? and loc = ?";
        	// deptno와 loc의 값을 ?로 지정한다.
            
        	pstmt = con.prepareStatement(sql);
        	
        	pstmt.setString(1, "10");	//첫번째 ?에 10 대입
        	pstmt.setString(2, "NEW YORK");	//두번째 ?에 New YORK 대입
			
        	rs = pstmt.executeQuery();
			
			while (rs.next()) {
        		int deptno =rs.getInt("x");
        		String dname = rs.getString("dname");
        		String loc = rs.getString("loc");
        		
				System.out.println(deptno+"\t"+dname+"\t"+loc);
        	}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs != null)rs.close();
				if(pstmt != null)pstmt.close();
				if(con != null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}

출력

호출 성공
10	ACCOUNTING	NEW YORK

  • 😁INSERT 예제
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCTest3 {

	public static void main(String[] args) {

		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String userid = "scott";
		String passwd = "tiger";
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, userid, passwd);
			String sql = "INSERT INTO dept VALUES(?, ?, ?)";
			int num = 0;
			
			pstmt = con.prepareStatement(sql);
			
			pstmt.setInt(1, 13);
			pstmt.setString(2, "개발");
			pstmt.setString(3, "서울");
			pstmt.executeUpdate();
			num++;
			
			pstmt.setInt(1, 14);
			pstmt.setString(2, "개발2");
			pstmt.setString(3, "서울2");
			pstmt.executeUpdate();
			num++;
			System.out.println(num);
			
			pstmt.close();	//pstmt를 SELECT로 출력하는 sql로
          	//변경하기 위해 실행중인 pstmt를 close() 해준다.
			
			pstmt = con.prepareStatement("SELECT * FROM dept");
			
			rs = pstmt.executeQuery();
			while(rs.next()) {
				System.out.println(rs.getInt(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3));
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(rs != null)rs.close();
				if(pstmt != null)pstmt.close();
				if(con != null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
	        
	}

}

출력

2
10	ACCOUNTING	NEW YORK
20	RESEARCH	DALLAS
30	SALES	CHICAGO
40	OPERATIONS	BOSTON
13	개발	서울
14	개발2	서울2

  • 😭UPDATE 예제
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCTest4 {

	public static void main(String[] args) {

		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String userid = "scott";
		String passwd = "tiger";
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, userid, passwd);
			
			String sql = "UPDATE DEPT SET LOC = ?, DNAME = ? WHERE DEPTNO=?";
			
			pstmt = con.prepareStatement(sql);
			
			pstmt.setString(1, "부산");
			pstmt.setString(2, "영업");
			pstmt.setInt(3, 14);
			
			int n = pstmt.executeUpdate();
			System.out.println(n);
			
			pstmt.close();
			
			pstmt = con.prepareStatement("select * from dept");
			
			rs = pstmt.executeQuery();
			
			while(rs.next()) {
				System.out.println(rs.getInt(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3));
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(rs != null)rs.close();
				if(pstmt != null)pstmt.close();
				if(con != null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
	        
	}

}

출력

0
10	ACCOUNTING	NEW YORK
20	RESEARCH	DALLAS
30	SALES	CHICAGO
40	OPERATIONS	BOSTON
13	개발	서울
14	부산	영업

  • 😭DELETE 예제
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

public class JDBCTest5 {

	public static void main(String[] args) {

		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String userid = "scott";
		String passwd = "tiger";
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, userid, passwd);
			
			String sql = "DELETE FROM DEPT WHERE DEPTNO = ?";
			
			pstmt = con.prepareStatement(sql);
			
			pstmt.setInt(1, 14);
			
			int n = pstmt.executeUpdate();
			System.out.println(n);
			
			pstmt.close();
			
			pstmt = con.prepareStatement("select * from dept");
			
			rs = pstmt.executeQuery();
			
			ResultSetMetaData rmd = rs.getMetaData(); //헤더정보
			int count = rmd.getColumnCount();	//헤더의 갯수
			for (int i = 1; i <= count; i++) {
				System.out.print(rmd.getColumnName(i)+"\t");
			}
			System.out.println();
			System.out.println("=====================================");
			
			while(rs.next()) {
				System.out.println(rs.getInt(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3));
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(rs != null)rs.close();
				if(pstmt != null)pstmt.close();
				if(con != null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
	        
	}

}

출력

1
DEPTNO	DNAME	LOC	
=====================================
10	ACCOUNTING	NEW YORK
20	RESEARCH	DALLAS
30	SALES	CHICAGO
40	OPERATIONS	BOSTON
13	개발	서울

❗DAO / DTO 패턴

데이터베이스를 연동하는 프로그램을 개발할 때 반드시 사용되는 2가지 개발 패턴이 있다.

DAO란? DTO란?

  • DAO (Data Access Object) 패턴

    GUI 화면을 구성하는 코드를 presentation logic 이라고 하며 GUI 화면에 데이터를 보여주기 위해서 데이터베이스를 검색하는 코드 및 GUI화면에서 새로 발생된 데이터(ex.회원가입)를 데이터베이스에 저장하는 코드에 같은 실제적인 작업을 하는 코드를 business logic 이라고 한다.


    presentation logicbusiness logic을 하나의 클래스로 모두 구현할 수 있고 여러 클래스로 모듈화 시켜서 구현할 수 있다.


    모듈화한 클래스들 중에서 데이터베이스 접근하는 코드만을 관리하는 클래스를 작성할 수 있는데 이 클래스 파일을 DAO 클래스라고 한다.
    일반적으로 DAO 클래스는 테이블 당 한 개씩 생성해서 사용한다. DAO 클래스 안에는 특정 테이블에서 수행할 작업을 메소드로 정의해서 구현하며 persentation logic에서는 DAO 클래스의 메소드를 호출하면서 원하는 작업을 구현하게 된다.


  • DTO (Data Transfer Object) 패턴

    presentation logicbusiness logic을 여러 클래스로 분리해서 작업은 하지만 서로 간에 긴밀한 관계가 유지되면서 작업이 이루어진다. presentation logic 에서 보여줄 데이터를 얻기 위해서 business logic에게 요청을 하면 business logic은 필요한 데이터를 DB에서 검사해서 presentation logic에 반환하는 작업등을 하게된다.


    이처럼 데이터를 다른 logic에게 전송 및 반환할 때 효율적으로 데이터를 사용할 수 있게 클래스를 작성할 수 있는데 이 클래스를 DTO 클래스라고 한다. 이름 그대로 데이터를 전송할 때 사용되는 클래스이다.
    DTO 클래스를 사용하면 데이터를 전송할 떄와 전송된 데이터를 얻어서 사용할 때 효율적으로 사용할 수 있는 장점이 있다.


DAO / DTO 코드 구현

  • 😁DeptDTO.java
package com.simpleDAO2;

public class DeptDTO {
	int deptno;
	String dname;
	String loc;
	
	public DeptDTO() {
		super();
		// TODO Auto-generated constructor stub
	}

	public DeptDTO(int deptno, String dname, String loc) {
		super();
		this.deptno = deptno;
		this.dname = dname;
		this.loc = loc;
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	public String getDname() {
		return dname;
	}

	public void setDname(String dname) {
		this.dname = dname;
	}

	public String getLoc() {
		return loc;
	}

	public void setLoc(String loc) {
		this.loc = loc;
	}

	@Override
	public String toString() {
		return "DeptDTO [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
	}
	
}
  • 😁DeptDAO.java
package com.simpleDAO2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class DeptDAO {
	
    String driver = "oracle.jdbc.driver.OracleDriver";
    String url = "jdbc:oracle:thin:@localhost:1521:xe";
    String userid = "scott";
    String passwd = "tiger";
	
	public ArrayList<DeptDTO> selectAllDept() {
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ArrayList<DeptDTO> list = new ArrayList<DeptDTO>();
		//`<DeptDTO>` 타입의 리스트에 add하기 위해 객체 생성 
        
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, userid, passwd);
			String sql = "select * from dept";
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {
				int deptno = rs.getInt(1);
				String dname = rs.getString(2);
				String loc = rs.getString(3);
                //DeptDTO 형식의 객체에 select 값 저장
				DeptDTO dto = new DeptDTO(deptno, dname, loc);
				list.add(dto);	//list.add로 저장
			}
			
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(rs!=null)rs.close();
				if(pstmt!=null)pstmt.close();
				if(con!=null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		return list;	//ArrayList<DeptDTO> 타입인 list를 리턴
	}
	
	
}
  • 😁JDBCTest.java
package com.simpleDAO2;

import java.util.ArrayList;

public class JDBCTest {

	public static void main(String[] args) {
		
		DeptDAO dao = new DeptDAO();	//DeptDAO 객체 생성
		ArrayList<DeptDTO> list = dao.selectAllDept();
        //반환된 list값을 새로운 <DeptDTO>형식의 list에 저장
		
        //list 출력
		for (DeptDTO d : list) {
			System.out.println(d.deptno + "\t" + d.dname + "\t" + d.loc);
		}

	}

}


SERVICE_DAO

위의 예제에서는 Main-DAO-DTO 형식으로 진행되었지만, 코드를 더 분리하여 Service를 추가했다.
더 분리하는 이유❗는 Bussiness LogicData Access Logic을 분리하여 코드의 응집성과 결합도, 유지 보수를 개선하기 위함이다.

일반적으로 SW개발은 코드의 유지 보수성과 확장성을 고려하여 코드를 모듈화 하고 분리하는 것이 중요하다.😁

비즈니스 로직은 애플리케이션의 핵심 기능과 비즈니스 규칙을 담당하며,
insert(), delete(), update() 등의 메서드를 구현한다. 이 메서드는 데이터 엑세스와 관련된 작업을 수행하기 위해 DAO클래스의 객체를 사용한다. 이 객체는 데이터베이스에 대한 CRUD(Create, Read, Update, Delete)작업을 수행하는 역할을 담당한다.

! 데이터 엑세스 로직은 데이터베이스와의 상호작용을 담당한다.

😋service 클래스를 추가한 이유는 코드의 구조화와 유지 보수성을 개선하기 위한 좋은 설계이다.


😋 코드 구현

  • OracleMain.java
import java.util.ArrayList;

import com.dto.Dept;
import com.service.OracleService;

public class OracleMain {

	public static void main(String[] args) throws Exception {

		OracleService service = new OracleService();
		
		//insert
		Dept xx = new Dept(99, "영업", "서울");
		int num = service.insert(xx);
		System.out.println("in main insert = " + num);
		
		//delete
		int num2 = service.delete(99);
		System.out.println("in main delete = " + num2);
		
		
		//update
		Dept xx2 = new Dept(99, "aa", "bb");
		try {
			int num3 = service.update(xx2);
			System.out.println("in main update = "+ num3);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//select
		try {
			ArrayList<Dept> list = service.select();
			
			for (Dept dept : list) {
				System.out.println(dept.getDeptno() + "\t" + dept.getDname()+ "\t" + dept.getLoc());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	

}
  • OracleService.java
    db의 4가지 정보와 Connection을 이 클래스에서 받는다.
    DAO 객체를 생성하고 메서드를 호출하여 main에 리턴한다.
package com.service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;

import com.dao.OracleDAO;
import com.dto.Dept;

public class OracleService {
	OracleDAO dao;
	// 1. 4가지 정보
	String driver = "oracle.jdbc.driver.OracleDriver";
	String url = "jdbc:oracle:thin:@localhost:1521:xe";
	String userid = "scott";
	String passwd = "tiger";
	
	public OracleService() {
		dao = new OracleDAO();	//dao드라이버 로딩완료
		try {
			Class.forName(driver);
			System.out.println("드라이버 로딩성공");
		} catch (ClassNotFoundException e) {
			System.out.println("드라이버 로딩 실패");
			e.printStackTrace();
		}
	}

	public ArrayList<Dept> select() throws SQLException {
		Connection con = null;
		ArrayList<Dept> list = null;
		try {
			con = DriverManager.getConnection(url, userid, passwd);
			list = dao.select(con);	
		}finally {
			if(con!=null) con.close();
		}
		return list;
	}

	public int insert(Dept xx) throws SQLException {
		Connection con = null;
		int n = 0;
		try {
			con = DriverManager.getConnection(url, userid, passwd);
			n = dao.insert(xx, con);
		}finally {
			if(con!=null) con.close();
		}
		return n;
	}

	public int delete(int deptno) throws SQLException {
		Connection con = null;
		int n = 0;
		try {
			con = DriverManager.getConnection(url, userid, passwd);
			n = dao.delete(deptno, con);
		}finally {
			if(con!=null) con.close();
		}
		return n;
	}

	public int update(Dept xx2) throws SQLException {
		
		Connection con = null;
		int n = 0;
		try {
			con = DriverManager.getConnection(url, userid, passwd);
			n = dao.update(xx2, con);
			try {
				if (n == 0) throw new Exception("zero update");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}finally {
			if(con!=null) con.close();
		}
		return n;

	}
	
	
    
}
  • OracleDAO.java
    DB에 대한 데이터 엑세스를 구현한 클래스이다.
package com.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.dto.Dept;

public class OracleDAO {

	public OracleDAO() {
		super();
	}
	
	public ArrayList<Dept> select(Connection con) throws SQLException {
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ArrayList<Dept> list = new ArrayList<>();
		
		try {
			System.out.println("con 연결 성공 "+con);
			String sql = "select * from dept";
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {
				int deptno = rs.getInt(1);
				String dname = rs.getString(2);
				String loc = rs.getString(3);
				Dept dto = new Dept(deptno, dname, loc); //레코드 하나를 객체로 저장
				list.add(dto);
			}
		}finally {
			if(rs != null)rs.close();
			if(pstmt != null)pstmt.close();
			if(con != null)con.close();
		}
		
		return list;
	}
	
	public int insert(Dept dto, Connection con) {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql="insert into dept (deptno,dname,loc)"
					+ " values (?,?,? )"; 

			pstmt = con.prepareStatement(sql);
			 pstmt.setInt(1, dto.getDeptno());
			 pstmt.setString(2,dto.getDname());
			 pstmt.setString(3,dto.getLoc());

			num= pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt != null)pstmt.close();
				if(con != null)con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return num;
	}
	
	public int delete(int deptno, Connection con) {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql = "delete from dept where deptno = "+deptno;
			pstmt = con.prepareStatement(sql);
			
			num = pstmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null)pstmt.close();
				if(con!=null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		return num;
	}

	public int update(Dept xx2, Connection con) throws SQLException {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql = "UPDATE DEPT SET LOC = '"+xx2.getLoc()+"', DNAME = '"+xx2.getDname()+"' WHERE DEPTNO = "+xx2.getDeptno();
			pstmt = con.prepareStatement(sql);
			num = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null)pstmt.close();
				if(con!=null)con.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		
		return num;
	}
}
  • Dept.java
package com.dto;

public class Dept {
	int deptno;
	String dname;
	String loc;
	
	public Dept() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Dept(int deptno, String dname, String loc) {
		super();
		this.deptno = deptno;
		this.dname = dname;
		this.loc = loc;
	}
	
	public Dept(int deptno) {
		super();
		this.deptno = deptno;
	}

	@Override
	public String toString() {
		return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	public String getDname() {
		return dname;
	}

	public void setDname(String dname) {
		this.dname = dname;
	}

	public String getLoc() {
		return loc;
	}

	public void setLoc(String loc) {
		this.loc = loc;
	}
	
}
  • RecordNotFoundException.java
package com.exception;

public class RecordNotFoundException extends Exception{

	public RecordNotFoundException(String message) {
		super(message);
	}
	
}


트랜잭션을 가지고 놀자

  • OracleTXMain.java
import java.util.ArrayList;

import com.dto.Dept;
import com.service.OracleService;

public class OracleTXMain2_tx {

	public static void main(String[] args) throws Exception {

		OracleService service = new OracleService();
		
		//insertDelete 99번부서 insert, 89번부서 delete
		service.insertDelete(new Dept(99, "개발", "제주"), 89);
		
		//insert
		Dept xx = new Dept(99, "영업", "서울");
		int num = service.insert(xx);
		System.out.println("in main insert = " + num);

		//delete
		int num2 = service.delete(99);
		System.out.println("in main delete = " + num2);
	
		//update
		Dept xx2 = new Dept(99, "aa", "bb");
		try {
			int num3 = service.update(xx2);
			System.out.println("in main update = "+ num3);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//selectAll
		try {
			ArrayList<Dept> list = service.select();
			for (Dept dept : list) {
				System.out.println(dept.getDeptno() + "\t" + dept.getDname()+ "\t" + dept.getLoc());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

앞서 구현한 예제 코드에서 추가한 코드

  • OracleService.java의 insertDelete() 메서드
public void insertDelete(Dept dept, int deptno) {
		Connection con = null;
		
		try {
			con = DriverManager.getConnection(url, userid, passwd);
	con.setAutoCommit(false);	//1. 자동 반영을 false로 변경, 수동으로 처리(commit, rollback)
			dao.insert(dept, con); //error없어서 insert 되게 함
			dao.delete(deptno, con); //delete시 exception 강제 발생
	con.commit();	//수동 커밋
		} catch (SQLException e) {
			if(con != null)
				try {
					System.out.println("RollBack=================");
	con.rollback();	//수동 롤백
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			System.out.println(e.getMessage());
		} finally {
			if(con != null)try {
	con.setAutoCommit(true); //다시 커밋 자동 반영 true
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
}

앞서 구현한 예제 코드에서 수정한 코드

  • OracleDAO.java의 insert, delete
package com.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.dto.Dept;

public class OracleDAO {

	public OracleDAO() {
		super();
	}
	
	public ArrayList<Dept> select(Connection con) throws SQLException {
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ArrayList<Dept> list = new ArrayList<>();
		
		try {
			System.out.println("con 연결 성공 "+con);
			String sql = "select * from dept";
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {
				int deptno = rs.getInt(1);
				String dname = rs.getString(2);
				String loc = rs.getString(3);
				Dept dto = new Dept(deptno, dname, loc); //레코드 하나를 객체로 저장
				list.add(dto);
			}
		}finally {
			if(rs != null)rs.close();
			if(pstmt != null)pstmt.close();
			if(con != null)con.close();
		}
		
		return list;
	}
	
	public int insert(Dept dto, Connection con) {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql="insert into dept (deptno,dname,loc)"
					+ " values (?,?,? )"; 

			pstmt = con.prepareStatement(sql);
			 pstmt.setInt(1, dto.getDeptno());
			 pstmt.setString(2,dto.getDname());
			 pstmt.setString(3,dto.getLoc());

			num= pstmt.executeUpdate();
			System.out.println("insert 실행 결과 " + num);
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt != null)pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return num;
	}
	
	public int delete(int deptno, Connection con) {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql = "dee from dept where deptno = ?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, deptno);
			
			num = pstmt.executeUpdate();
			System.out.println("실행 결과" + num);
			
		} catch (SQLException e) {
			try {
				System.out.println("in dao.delete Rollback================");
				con.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null)pstmt.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		return num;
	}

	public int update(Dept xx2, Connection con) throws SQLException {
		PreparedStatement pstmt = null;
		int num = 0;
		try {
			String sql = "UPDATE DEPT SET LOC = '"+xx2.getLoc()+"', DNAME = '"+xx2.getDname()+"' WHERE DEPTNO = "+xx2.getDeptno();
			pstmt = con.prepareStatement(sql);
			num = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null)pstmt.close();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		return num;
	}
}

OracleServiceinsertDelete() 함수에서 dao.insert() 종료 후, 바로 dao.delete()를 하는데, insert에서 Connection을 close() 해버리면 dao.delete()에서 Connection을 사용하지 못하기 때문에 OracleDAO의 insert, delete 함수에서 Connection을 close()하면 안된다.


0개의 댓글