::: 강좌/소스/문서 :::

강좌/소스/문서 성격에 맞지 않는 광고,비방,질문의 글은 즉시 삭제하며
내용을 복사하여 사용할 경우 반드시 이곳(http://www.howto.pe.kr)을 출처로 명시하여 주세요


Category

  신훈재(2004-06-18 13:46:53, Hit : 6137, Vote : 1357
 [자바] JDBC 코딩시 주위사항(jsp, servlet)

[ JDBC 코딩시 주위사항(jsp, servlet) - javaservice.net 이원영 참조]


catch블록은 예외가 발생했을 때만 실행.
finally블록은 예외가 발생했든 안했든 항상 실행.

--------------------------------------------------------------------------------
1. 전역변수로 두지 않는다.(인스턴스 변수의 공유문제, 쓰레드 동작문제)
    와야할 경우에는 변하지 않는 값일 경우 final 처리.
  
   <%!
        private static final String USERID = "scott"; // <--- 변하지 않는 값일 경우
        private static final String PASSWORD = "tiger"; // <--- 변하지 않는 값일 경우
  
       //Connection conn = null; // <--- 여기에 두면 안된다. !!!
       //Statement stmt = null; // <--- 여기에 두면 안된다. !!!
   %>

   <%
       Connection conn = null; // <--- 이 쪽으로 와야죠 !!!
       Statement stmt = null; // <--- 이 쪽으로 와야죠 !!!
       conn = ...
       stmt = .....
   %>
--------------------------------------------------------------------------------
1. Connection을 init(), jspInit()에서 미리 연결해 두고 사용하지 말자.
   ( DB 연결자원의 낭비, 수많은 동시사용자에 대한 처리한계, Transaction 처리를 보장받을 수 없다. )

     private ServletContext context;
     private Connection conn = null;  <--- !!!

     public void init(ServletConfig config) throws ServletException
     {
         super.init(config);
         context = config.getServletContext();
         try {
             Class.forName(drv);
             conn = DriverManager.getConnection(url,user,password);
         }
         catch (SQLException e) { throw new ServletException("Unable to connect to database:"+ e.toString()); }
     }
--------------------------------------------------------------------------------
1. 에러가 발생했을 때도 close() 되야한다.
   ( Connection 뿐만 아니라 Statement, ResultSet 도 반드시 닫혀야 한다. )
   ( ResultSet은 Statement 가 close() 될 때 함께 자원이 해제됩니다. )

   Connection conn = null;
   Statement stmt = null;
   ResultSet rs = null;
   String id = req.getParameter ( "id" );
   try {
      conn = DriverManager.getConnection ( "url...", "id", "password" );
      stmt = conn.createStatement ( );
      rs = stmt.executeQuery ( "sselect * from XXX where id = '" + id + "'" );
      while ( rs.next ( ) )
      {
         ......  
      }
   }
   catch (SQLException e) { throw new ServletException("Unable to connect to database:"+ e.toString()); }
   finally {
      if ( stmt != null ) try { stmt.close ( ); } catch ( Exception e ) { } //...finally { tyr ( if().. if().. } catch()... } 이렇게 하지 말라.
      if ( conn != null ) try { conn.close ( ); } catch ( Exception e ) { }
   }
--------------------------------------------------------------------------------
1. stmt가 인스턴스 변수라 하더라도 stmt = conn.createStatement()가 수행될 때 마다 생성되므로
   각기 다른 인스턴스로 다르게 close() 해주어야 한다.

  Connection conn = null;
  Statement stmt1 = null;
  Statement stmt2 = null;
  try{
     conn = ...<getConnection()>...;
     stmt1 = conn.createStatement();
     stmt2 = conn.createStatement();
     ResultSet rs = stmt1.executeQuery("select deptno ...where id ='"+ id +"'");
     while(rs.next()){
       String deptno = rs.getString("deptno");
       stmt2.executeUpdate("update set dept_name = ... where deptno = '"+ deptno +"'");
       ......
     }
     rs.close();
  }
  catch(Exception e){}
  finally {
     if ( stmt1 != null ) try{stmt1.close();}catch(Exception e){}
     if ( stmt2 != null ) try{stmt2.close();}catch(Exception e){}
     if ( conn != null ) ...<releaseConnection()>...;
  }
  ---------------------------------------------------------------------------------------------
  Connection conn = null;
  Statement stmt = null;
  try {
    conn = DriverManager.getConnection ( "url...", "id", "password" );
    stmt = conn.createStatement(); // ...(1)
    rs = stmt.executeQuery("select a from test1...");
    .....
    stmt = conn.createStatement(); // ...(2) 먼저 생성된 (1)을 덮쳐서 되어 (1)이 영원히 close() 되지 않는다.
    rs = stmt.executeQuery("select a from test2..."); // ...그냥 (2)를 주석처리하고 rs.close()한다음, 한번 생성한 stmt을 반복해서 쓰면된다.
    ....
  }
  finally{
    if ( stmt != null ) try{stmt.close();}catch(Exception e){} //단지 (2)의 것만 닫을 뿐이다.
    if ( conn != null ) try { conn.close ( ); } catch ( Exception e ) { }
  }
--------------------------------------------------------------------------------
1. 반복제어문에서 사용할 경우

  Connection conn = null;
  PreparedStatement pstmt = null;
  try {
    conn = DriverManager.getConnection ( "url...", "id", "password" );
    pstmt = conn.prepareStatement("update .... ?... where id = ?");
    for(int i=0;i<10;i++)
    {
      //pstmt = conn.prepareStatement("update .... ?... where id = ?"); //이렇게 오면 안된다. 9개는 닫히지 않는다.
      pstmt.clearParameters(); //...파라메타를 지울 때 사용.
      pstmt.setString(1,"xxxx");
      pstmt.setString(2,"id"+(i+1) );
      int affected = pstmt.executeUpdate();
      
      if ( affected == 0 ) throw new Exception("NoAffected"); //... 제대로 수행되었으나 에러인 경우
      else if ( affedted > 1 ) throw new Exception("TooManyAffected"); //... 제대로 수행되었으나 에러인 경우
    }
  }
  finally {
     if ( pstmt != null ) try {pstmt.close();}catch(Exception e){}
     if ( conn != null ) try { conn.close ( ); } catch ( Exception e ) { }
  }
--------------------------------------------------------------------------------
1. 데이타 값이 없을 경우에 대비하라.

  public void someMethod(String empno) throws Exception {
      Connection conn = null;
      Statement stmt = null;
      try{
         conn = ...<getConnection()>...;
         stmt = conn.createStatement();
         int affected = stmt.executeUpdate(
             "UPDATE emp SET name='이원영' WHERE empno = '" + empno + "'"
         );
         if ( affected == 0 ) throw new Exception("NoAffectedException"); //... 이 부분
         else if ( affected > 1 ) throw new Exception("TooManyAffectedException"); //... 이 부분
      }
      finally {
         if ( stmt != null ) try{stmt.close();}catch(Exception e){}
         if ( conn != null ) ...<releaseConnection()>...;
      }
  }
--------------------------------------------------------------------------------
1. 트랜잭션 처리에 주위하라.

  "conn.setAutoComm(false); 상태에서 한번 실행된 Update성 SQL Query는 이유를
   막론하고 어떠한 경우에도 commit() 이나 rollback() 되어야 한다."

  Connection conn = null;
  Statement stmt = null;
  try{
     conn = ...<getConnection()>...;
     conn.setAutoCommit(false); //... 이렇게 해야 수동 제어가 된다.
     stmt = conn.createStatement();
     stmt.executeUpdate("UPDATE ...."); // -------- (1)
     stmt.executeUpdate("DELETE ...."); // -------- (2)
     stmt.executeUpdate("INSERT ...."); // -------- (3)

     conn.commit(); // <-- 반드시 try{} 블럭의 마지막에 와야 합니다.
  }
  catch(Exception e){
     if ( conn != null ) try{conn.rollback();}catch(Exception ee){}
     throw e;  // <--- 필요한 경우, 호출한 곳으로 Exception상황을 알려줄수도 있습니다
  }
  finally {
     if ( stmt != null ) try{stmt.close();}catch(Exception e){}
     if ( conn != null ) ...<releaseConnection()>...;
  }
  -------------------------------------------------------------------
  Connection conn = null;
  Statement stmt = null;
  try{
     conn = ...<getConnection()>...;
     conn.setAutoCommit(false);
     stmt = conn.createStatement();
     stmt.executeUpdate("UPDATE ....");
     ResultSet rs = stmt.executeQuery("SELECT ename ...");
    
     if ( rs.next() ) conn.commit();
     else conn.rollback();
    
     rs.close();
  }
  catch(Exception e){  // <---- !!!!!
     if ( conn != null ) try{conn.rollback();}catch(Exception ee){}
     throw e;
  }
  finally {
     if ( stmt != null ) try{stmt.close();}catch(Exception e){}
     if ( conn != null ) ...<releaseConnection()>...;
  }  
--------------------------------------------------------------------------------
1. 쿼리하는 컬럼을 지정하느냐 아니면 * 를 써서 모두 가져오느냐가 큰 성능의 차이를 보인다.
   6초 이상 걸리던 쿼리가 단 0.2 초만에 해결되었습니다.
  
   select * from test
   select name, email from test
--------------------------------------------------------------------------------
1. 몽땅 가져와서 rs.next()로 돌려서 위치를 찾는 것 보다는 sql에서 게시물 수만큼 가져와서 뿌려주는 것이 낳다.

   1) 오라클 게시판에서 rownum을 이용한 경우
  
      select * from (
        select * from (
          select record_no, record_depth, record_depthno, record_title, record_writer,
          writer_email, to_char(record_date,'yyyy/mm/dd') record_date,  read_count
          from pm2000_qna order by record_no desc, record_depth
        ) where rownum <= ? order by rownum desc
      ) where rownum <= ? order by rownum desc
      
      pstmt.setInt(1,(pageNo+1)*pageSize);  // pageNo는 0부터..
      pstmt.setInt(1,pageSize);
      ------------------------------------------------------------
      select DocumentNo, seqNum
      from
      (
          select DocumentNO, rownum seqNum
              from
              (
                  select DocumentNo
                      from Order
                          order by CreateDate desc
              )
              where rownum <= 10
      )
      where seqNum >= 1;

      DOCUMENTNO                                   SEQNUM
      --------------------------------------------------
      20010630-2125                                     1
      20010630-2124                                     2
      20010629-2123                                     3
      20010629-2122                                     4
      20010629-2121                                     5
      20010629-2120                                     6
      20010629-2119                                     7
      20010629-2118                                     8
      20010629-2113                                     9
      20010629-2114                                    10
      
   2) 오라클 게시판에서 index을 이용한 경우.
  
      cursor_pos = ((pagenum - 1) * NumberOfArticlePerPage) + 1;
      pstmt = db.prepareStatement("
         select no,ndate,name,email,title,text,refer,recnt,rede,rnum from (
            select /*+ index_desc(board BOARD_NO_PK) */ no,to_char(ndate,'YYYY-MM-DD AM HH24:MI:SS') as ndate,name,email,title,text,refer,recnt,rede,rownum as rnum from board where sorting=0
         ) where rnum between ? and  ?");  
      pstmt.setInt(1,cursor_pos);
      pstmt.setInt(2,(cursor_pos + NumberOfArticlePerPage -1));
      
      저는 일단 답변이 없는 게시물만 query를 먼저 하기때문에, where sorting=0 부분이 추가되었습니다.
      답변글까지 한방에 처리할려면, sorting=0인 부분을 지우고, order by sorting를 사용해야 될것 같네요.
  
   3) 위의 mysql 버전.
  
      select record_no, record_depth, record_depthno, record_title, ...
      from pm2000_qna order by seq desc limit ?, ?
      
      pstmt.setInt(1,pageNo*pageSize);  // pageNo는 0부터..
      pstmt.setInt(1,pageSize);
--------------------------------------------------------------------------------
1. order by column desc를 생략하기 위해서 insert시에 max value에서 값을 감소시 키는 방식을 채택할 수 있다.

   그리고 가능하다면 record_no는 글이 등록될 때마다 값을 증가시키지 말고 감소시키면 더 빨라질겁니다.
   예를 들어 0부터 시작해서 계속 1씩 빼는거죠. 0 -1 -2 -3
   이렇게 하면 order by record_no desc 를 해 줄 필요없이 그냥 order by record_no하면 되죠.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------  








23   [Java/PHP] [자바] DB 컨넥션 풀  신훈재 2004/06/18 9511 1857
22   [Java/PHP] [자바] JDBC-ODBC 연결 예제  신훈재 2004/06/18 9046 1672
21   [Java/PHP] [자바] 시스템 프로퍼티를 이용한 드라이버 로드  신훈재 2004/06/18 5487 1425
20   [Java/PHP] [자바] 오라클 각종 에러  신훈재 2004/06/18 6490 1671
19   [Java/PHP] [자바] 활용팁(오라클)  신훈재 2004/06/18 5997 1603
18   [Java/PHP] [자바] ResultSet 질의결과  신훈재 2004/06/18 6111 1317
17   [Java/PHP] [자바] Select예제  신훈재 2004/06/18 6249 1562
16   [Java/PHP] [자바] Update예제  신훈재 2004/06/18 5414 1333
15   [Java/PHP] [자바] Insert 예제  신훈재 2004/06/18 6493 1673
14   [Java/PHP] [자바] Query Statement  신훈재 2004/06/18 7763 1468
13   [Java/PHP] [자바] JDBC Connect  신훈재 2004/06/18 6718 1489
  [Java/PHP] [자바] JDBC 코딩시 주위사항(jsp, servlet)  신훈재 2004/06/18 6137 1357
11   [Java/PHP] [자바] 여러종류의 데이타베이스 테스트 소스  신훈재 2004/06/18 6421 1457
10   [Java/PHP] [자바] JDBC 테스트 소스(오라클)  신훈재 2004/06/18 5436 1345
9   [Java/PHP] [소스] snmp 를 이용한 시스템 가용율 구하기 예제  김영대 2003/12/01 9570 2092
8   [Java/PHP] [소스] Oolong 언어를 이용한 Factorial 계산 프로그램 예제  김영대 2003/11/10 6633 1683
7   [Java/PHP] [문서] Java Web Services Development Pack (JWSDP) 1.0 tutorial  김영대 2003/03/24 5851 1457
6   [Java/PHP] [문서] Java Swing v1.1.1 도움말  김영대 2003/03/24 5782 1470
5   [Java/PHP] [문서] Java Servlet Development Kit (JSDK) v2.3 도움말  김영대 2003/03/24 5520 1454
4   [Java/PHP] [문서] Java 2 SDK, Enterprise Edition (J2EE) 1.3.1 도움말  김영대 2003/03/24 5617 1469

1 [2]
 

Copyright 1999-2017 Zeroboard / skin by zero