ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [7회차] JDBC (기타 예제, DAO와 DTO-②)
    ORACLE 2021. 5. 5. 18:17

    강의명 : 오픈프레임워크 활용 디지털융합 SW엔지니어 양성 과정

    강의 날짜 : 21.05.04

     

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class PreviousPrepareTest {
    
    		Connection conn;
    		//static 블록
    		static {
    			try {
    				Class.forName("oracle.jdbc.driver.OracleDriver");
    			}catch ( ClassNotFoundException cne) {
    				cne.printStackTrace();
    			}
    		}
            
    		public void connect() {
    			try {
    				String url = "jdbc:oracle:thin:@localhost:1521:xe";
    				conn = DriverManager.getConnection(url,"lion","1234");
    			}catch (SQLException se) {
    				se.printStackTrace();
    			}
    		}
    		
    		public void select() {
    			ResultSet rs=null;
    			PreparedStatement pstmt=null;
    			try {
    				String sql = "SELECT * FROM MEMBER";
    			pstmt=conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,
    					ResultSet.CONCUR_UPDATABLE);
    			rs=pstmt.executeQuery();
                
    			System.out.println("다음 : 앞으로 이동하면서 출력");
    			while (rs.next()) { 
    				for(int i = 1;i<=6;i++) 
    					System.out.print("\t"+ rs.getString(i));
    				System.out.println();
    				
    			}
                
    			System.out.println("뒤로 이동하면서 출력");
    			while(rs.previous()) {
    				for(int i =1;i<=6;i++) {
    					System.out.print("\t"+ rs.getString(i));}
    				System.out.println();
    			}
    			
    			System.out.println("첫 번째 레코드");
    			if(rs.first()) {
    				for(int i =1;i<=6;i++)
    					System.out.print("\t"+ rs.getString(i));
    				System.out.println();
    			}
                
    			System.out.println("마지막 레코드");
    			if(rs.last()) {
    				for(int i =1;i<=6;i++)
    					System.out.print("\t"+ rs.getString(i));
    				System.out.println();
    		}
            
    			System.out.println("세 번째 레코드");
    			if(rs.absolute(3)) { //가장 많이 쓰이는 메소드
    				for(int i =1;i<=6;i++)
    					System.out.print("\t"+ rs.getString(i));
    				System.out.println();
    			}
    
    		}catch(SQLException se) {
    			se.printStackTrace();
    		}finally {
    			try {
    				rs.close();
    				pstmt.close();
    				conn.close();
    		
    			}catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	public static void main (String[] args) {
    		PreviousPrepareTest ppt = new PreviousPrepareTest();
    		ppt.connect();
    		ppt.select();
    	}
    }

     

    1. static 블록

     

    static은 컴파일 할 때 메모리가 할당된다.

    즉, static 블록은 가장 최우선으로 실행하고자 하는 것이 있다면 사용하는 것이다.

     

    위의 예제는 드라이버 로딩을 컴파일 시점에 미리 실행한 것이다.

     

     

    2. ResultSet의 데이터 출력

     

    ResultSet의 커서의 방향은 한 방향이라서 데이터를 조회할 때 비효율적이다.

     

    ResultSet.TYPE_SCROLL_INSENSITIVE, 

    ResultSet.CONCUR_UPDATABLE

    → 자유롭게 커서의 위치를 조정하여 원하는 위치로 갱신이 가능하게 해준다.

    이 작업은 Statement 객체를 준비할 때 한다.

     

    커서의 위치 관련 메소드 설명
    next() 차례대로 앞으로 위치가 변경
    previous() 뒤에서 차례대로 위치가 변경
    first() 첫 번째 레코드
    last() 마지막 레코드
    absolute(N) N 번째 레코드 

     

     

    3. JAVA의 트랜잭션

     

     

     

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class TransanctionTest {
    	Connection conn;
        
    	static {
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    		}catch ( ClassNotFoundException cne) {
    			cne.printStackTrace();
    		}
    	}
    	//DB에 연결    
    	public void connect() {
    		try {
    			String url = "jdbc:oracle:thin:@localhost:1521:xe";
    			conn = DriverManager.getConnection(url,"lion","1234");
    			conn.setAutoCommit(false); //자동 커밋이 되지 않도록 함
    			System.out.println("Connection Success!");
    		}catch (SQLException se) {
    			se.printStackTrace();
    		}
    	}
    	//값 INSERT
    	public void insert() {
    		connect(); //연결 메소드 호출
    		Statement stmt = null;
    		boolean isOrderSuccess = false; //실행 성공 여부 false로 초기화
    		//INSERT가 문제없이 진행된 경우        
    		try { 
    			stmt = conn.createStatement();
    			String sql = "INSERT INTO PAY VALUES ('aaa', '001', 1000)";
    			stmt.executeQuery(sql); //INSERT 실행
    			sql = "INSERT INTO ORDERLIST VALUES ('001', 'p2014001')";
    			stmt.executeQuery(sql); //INSERT 실행
    			isOrderSuccess = true; //실행 후 실행 성공 여부에 true값 대입
    		
    		}catch(SQLException se) { //INSERT에서 문제가 발생한 경우
    			System.out.println("insert fail");
    			se.printStackTrace();
    		}finally { //INSERT 성공 여부와 관계없이 수행
    			if(isOrderSuccess) { //INSERT문 성공의 경우는 true
    				try {
    					conn.commit(); //true라면 commit으로 확정
    				}catch(Exception e) {
    					e.printStackTrace();
    				}
    			}
    			else { // INSERT문 진행 시 catch된 경우는 값이 바뀐 적이 없으므로 false
    				try {
    					conn.rollback(); //false라면 rollback으로 복구
    				}catch(Exception e) {}
    			}
    			try {
    				stmt.close();
    				conn.close();
    			}catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	//실행 메소드    
    	public static void main(String[] args) {
    		TransanctionTest tt = new TransanctionTest();
    		tt.insert(); //insert메소드 호출
    	}
    }

     

     

     

    오류가 나지 않아 isOrderSuccess가 true로 바뀌었고, commit이 되어 

    cmd에서 테이블을 확인할 수 있다.

     

     

    한 번 더 실행한 경우

    이 때, PAY 테이블의 MEMID와 ORDERLIST의 ORDERLIST는 PRIMARY키로 중복값을 가질 수 없다.

    그러므로 같은 소스를 한 번 더 실행하면 catch되어 예외 처리가 되고,

    isOrderSuccess는 바뀐 적이 없어, 그대로 false이므로 rollback된다.

     

    트랜잭션은 은행 업무에 많이 사용된다.

    확정이 되거나 실행 실패의 경우는 확정이 아니라 철회시켜야 하는 작업이 중요하기 때문이다.

     

     

     

    3. toString 메소드

     

    클래스 안에 toString메소드를 오버라이딩해주면,

    그 객체를 출력했을 때 알라서 toString()를 호출하여 return해준다.

     

    만약 toString이 없으면 객체의 주소를 찍어준다.

     

    즉, toString은 그 객체가 가진 데이터를 String화해서 반한해주는 것이다.

     

     

     

    4. 다이어그램 그리기

     

    //main클래스
    import java.util.Scanner;
    
    public class LoginMain {
    
    	public static void main(String[] args) {
    		boolean isStop = false; 
    		Scanner sc = new Scanner(System.in); 
    		LoginSVC loginSVC = new LoginSVC();
    		do {
    			System.out.println("로그인 화면");
    			System.out.println("아이디와 비밀번호를 입력하세요");
    			System.out.println("아이디 : ");
    			String id = sc.next(); 
    			System.out.println("비밀번호 : ");
    			String passwd = sc.next(); 
    			User user = loginSVC.login(id,passwd); 
    			if(user == null) {
    				System.out.println("아이디나 비밀번호가 일치하지 않습니다.");
    			}
    			else {
    				System.out.println("로그인한 사용자 정보");
    				System.out.println(user);
    				isStop = true;
    			}
    		}while(!isStop);
    		sc.close();
    	}
    }
    //DAO역할의 서비스 객체
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class LoginSVC {
    	Connection conn;
    	static {
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    		}catch ( ClassNotFoundException cne) {
    			cne.printStackTrace();
    		}
    	}
    	
    	public void connect() {
    		try {
    			String url = "jdbc:oracle:thin:@localhost:1521:xe";
    			conn = DriverManager.getConnection(url,"lion","1234");
    			conn.setAutoCommit(false);
    			System.out.println("Connection Success!");
    		}catch (SQLException se) {
    			se.printStackTrace();
    		}
    	}
    	
    	public User login(String id, String passwd) {
    		User user = null;
    		Statement stmt = null;
    		ResultSet rs = null;
    		
    		try {
    			connect();
    			stmt = conn.createStatement();
    			String sql = "SELECT * FROM MEMBER WHERE ID = '"+id
    					+"' AND "+"PASSWD = '"+passwd+"'";
    			rs=stmt.executeQuery(sql);
    			if(rs.next()) {
    				id=rs.getString("id");
    				passwd=rs.getString("passwd");
    				String name = rs.getString("name");
    				int age =rs.getInt("age");
    				String addr = rs.getString("addr");
    				String email = rs.getString("email");
    				user = new User(id, passwd, name, age, addr, email); 
    			}
    		}catch(SQLException se) {
    			se.printStackTrace();
    		}finally {
    			try {
    				rs.close();
    				stmt.close();
    				conn.close();
    			}catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return user;
    	}
    }
    //DTO 
    public class User { 
    	private String id;
    	private String passwd;
    	private String name;
    	private int age;
    	private String addr;
    	private String email;
    	
    	public User(String id, String passwd, String name, int age, String addr, String email) {
    		this.id = id;
    		this.passwd = passwd;
    		this.name = name;
    		this.age = age;
    		this.addr = addr;
    		this.email = email;
    	}
    	
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getPasswd() {
    		return passwd;
    	}
    	public void setPasswd(String passwd) {
    		this.passwd = passwd;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public String getAddr() {
    		return addr;
    	}
    	public void setAddr(String addr) {
    		this.addr = addr;
    	}
    	public String getEmail() {
    		return email;
    	}
    	public void setEmail(String email) {
    		this.email = email;
    	}
    
    	@Override
    	public String toString() {
    		return "User [id=" + id + ", passwd=" + passwd + ", name=" + name + ", age=" + age + ", addr=" + addr
    				+ ", email=" + email + "]";
    	}
    }

    다이어그램

    소스를 보면서 다이어그램화 시키는 것이 파악하기 가장 용이하다.

    다이어그램은 모든 것을 담는 것이 아니라 중요한 데이터의 흐름을 파악하는 것이므로,

    필수적인 데이터, 필수적인 명령문, 필수적인 정보만 담아도 된다.

     

    *시퀀스는 특수 제약조건이므로,

    NOT NULL, UNIQUE, DEFAULT, CHECK, FOREIGN KEY와 같이 제약조건을 적어주도록 한다.

     

    * 서비스 객체는 DAO의 역할을 하지만 DAO의 기능 이외에도 여러 처리 기능을 하는 객체이다.

Designed by Tistory.