21.02.05


[DataBase - Statement]

<%
  //1. DB접속
  //1-1. context.xml을 객체화 해서 가져온다.
  Context ctx = new InitialContext();
  //1-2. name을 통해서 해당 Resource를 찾아 DataSource로 변환해준다.
  DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle");
  //1-3. DataSource를 통해 Connection을 가져온다.
  Connection conn = ds.getConnection();
  if(conn != null){
      out.println("<h2>연결완료</h2>");
  }
  //2. 쿼리실행
  //2-1. 쿼리문 준비
  String sql = "CREATE TABLE member("
		+"id VARCHAR2(50),"		
		+"pw VARCHAR2(200),"
		+"name VARCHAR2(50),"
		+"age NUMBER(4),"
		+"gender VARCHAR2(4),"
		+"email VARCHAR2(100),"
		+"reg_date DATE DEFAULT SYSDATE"
		+")";
  //2-2. Statement 준비
  Statement stmt = conn.createStatement();
  //3.쿼리문 실행
  int cnt = stmt.executeUpdate(sql);
  System.out.println("cnt:" +cnt); //테이블 생성은 데이터와 관련된 것이 아니므로 0반환
  out.print("<h3>테이블생성완료</h3>");
  //3. 자원반납
  conn.close();
%>
- 한번 실행 후 다시 실행되지 않는다면 Statement가 낫다.
- 순서
	1. DB접속
    	1-1) context.xml 객체화
    	1-2) name을 이용해서 Resource를 찾아 DataSource로 변환
    	1-3) DataSource를 통해 Connection을 가져온다.
	2. 쿼리실행
    	2-1) 쿼리문 준비
        2-2) Connection을 이용해 Statement준비
          - connction.crateStatement()
    	2-3) 쿼리문 실행
    	  - executeUpdate() : DB에 변화를 줄 경우 사용한다.(UPDATE,DELETE,INSERT)
		  - executeUpdate() 사용시 반환되는 int는 적용에 성공한 데이터 개수이다.
    	  - 위내용으로는 테이블 생성은 데이터와 관련된 것이 아니므로 0반환된다.
     3. 자원반납

[DataBase - PreparedStatement]

<%
  //1.DB접속
  Context ctx = new InitialContext();
  DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle");
  Connection conn = ds.getConnection();
  System.out.println(conn);
  //2. 쿼리실행
  //2-1. 쿼리문준비
  String sql = "INSERT INTO member(id,pw,name,age,gender,email) VALUES(?,?,?,?,?,?)";
	
  //2-2. Connection으로 부터 PreparedStatement 가져오기
  PreparedStatement pstmt = conn.prepareStatement(sql);
	
  //pstmt는 각?에 무엇이 들어가는지 알려줘야한다.
  for(int i=1;i<=5;i++){
	pstmt.setString(1, "admin"+i);//첫번째 물음표에 admin 삽입
	pstmt.setString(2, "pass"+i);
	pstmt.setString(3, "user"+i);
	pstmt.setInt(4, 20+i);
	pstmt.setString(5, "남");
	pstmt.setString(6, "[email protected]");
		
	//2-3. 쿼리 실행(executeQuery,executeUpdate)
  	if(pstmt.executeUpdate()!=0){
	  out.println("<h3>"+i+"번째 데이터 입력완료</h3>");
  	}
  }
  //3. 자원반납
  conn.close();
%>
- Statement 보다 PreparedStatement 훨씬 많이 사용한다.
- 문장을 컴파일 한 후 재사용한다.
- 그래서 문장이 여러번 반복 될 때 유리하며 성능과 속도 면에서 유리하다.
- 순서
	1. DB접속
    	1-1) Context.xml 객체화
    	1-2) name으로 Resource를 찾아 DataSource로 변환
    	1-3) DataSource를 이용해 Connection 가져오기
    2. 쿼리실행
    	2-1) 쿼리문준비
        2-2) Connection으로 부터 PreparedStatement 가져오기
        2-3) 각 ?에 값 넣어주기
        2-4) 쿼리 실행
    3. 자원반납

[DataBase - ResultSet]

<%	
  //1. DB접속
  Context ctx = new InitialContext();
  DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle"); 
  Connection conn = ds.getConnection();
  //2. 쿼리실행
  //2-1. 쿼리문 준비
  String sql = "SELECT * FROM member";
  //2-2. Connection으로 부터 PreparedStatement가져오기
  PreparedStatement pstmt = conn.prepareStatement(sql);
  //2-3. ?대응 - 이번 쿼리는 ?가 없으므로 사용안함
  //2-4. 쿼리 실행
  ResultSet rs= pstmt.executeQuery();
  System.out.println(rs);
  //다음값이 있으면 T 없으면 F
  while(rs.next()){//다음값이 있나?
	out.print("<p>"
	+rs.getString(1)+" | "
	+rs.getString("pw")+" | " 
	+rs.getInt("age")+" | "
	+rs.getString("gender")+" | " 
	+rs.getString("email")+" | "
	+rs.getDate("reg_date")
	+"</p>");
  }
  //ResultSet에서 metadata를 뽑을 수 있다.
  ResultSetMetaData meta = rs.getMetaData();
  /*desc명령어와 유사하다.*/
  out.println("<p>컬럼수:"+meta.getColumnCount()+"</p>");
  //컬럼의 이름과 타입, 사이즈
  for(int i=1;i<=meta.getColumnCount();i++){
	out.println(meta.getColumnName(i)
    	+" "+meta.getColumnTypeName(i)+"("+meta.getColumnDisplaySize(i)
		+")"+"</br>");
  }
  //3. 자원반납
  rs.close();
  conn.close();
%>
- executeQurey() 는 값을 조회하는 쿼리를 실행 해 주는 메서드 이다.
- 때문에 결과값을 ResultSet 객체로 반환한다.
- ResultSet에서 metadata를 뽑을 수 있다.
- 순서
	1. DB접속
    2. 쿼리실행
    	2-1) 쿼리문준비
        2-2) Connection으로 부터 PreparedStatement 가져오기
        2-3) ?대응 - 이번 쿼리는 ?가 없으므로 사용안함
        2-4) 쿼리 실행
       	  - next() 다음행으로 커서 이동(데이터 존재 여부를 boolean 으로 반환)
          - executeQuery() : 반환되는 데이터가 있을경우 사용한다.(SELECT)
		  - getTYPE(컬럼인덱스지정) : 해당데이터를 지정한 타입으로 가져온다.
		  - getTYPE(컬럼명지정) : 해당데이터를 지정한 타입으로 가져온다.

[Data Base – Transaction]

<%
  //1.DB접속
  Context ctx = new InitialContext();
  DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle");
  Connection conn = ds.getConnection();
  conn.setAutoCommit(false);//트랙젝션 수동 설정
	
  try{
	//2.쿼리실행(쿼리1 : 정상, 쿼리2 : 비정상)
	String sql1 = "INSERT INTO member(id,pw,name,age,gender,email) 
    	VALUES('tranx2','pass','관리자','40','남','[email protected]')";
	PreparedStatement ps = conn.prepareStatement(sql1);
	int success = ps.executeUpdate();
	System.out.println("success1 : " + success);
	ps.close();
		
	//실패가 났을 경우 ..sql1의 쿼리 실행도 취소가 되는가?
	String sql2 = "INSERT INTO member2(id,pw,name,age,gender,email) 
    	VALUES('tranx2','pass','관리자','40','남','[email protected]')";
	ps = conn.prepareStatement(sql2);
	success = ps.executeUpdate();
	System.out.println("success2 : " + success);
	conn.commit();
	out.println("<h3>커밋하겠습니다.</h3>");
	ps.close();
  }catch(Exception e){
	e.printStackTrace();// 개발자만 확인할수 있도록 처리
	conn.rollback();
	out.println("<h3>쿼리 실행중 문제가 발생하여 롤백 하였습니다.</h3>");
  }finally{
	conn.close();
  }
%>
- transaction : DB에서 사용되는 쪼갤 수 없는 업무처리의 단위이다.(ex.인터넷뱅킹)
- 트랜젝션 수동 설정을 안해줬을 경우에 비정상쿼리가 있더라도 정상쿼리는 DB랑 연결되어 
  데이터가 들어가게 된다.
- 그래서 트랜젝션 수동 설정을 해줘야한다.
- try-catch문을 만들어 예외발생시 rollback()하게 한다.