이상 데이터베이스 연결 잠 금

내 가 접촉 한 소프트웨어 개발 자 중에서 N 이 여러 차례 데이터베이스 잠 금 문 제 를 들 었 다.솔직히 누군가가 그들 에 게 데이터베이스 잠 금 문 제 를 보고 하 는 것 을 들 을 때마다 나 는 항상 의아 하고 그들의 코드 에 문제 가 있다 고 의심 했다.각종 이상 이 합 리 적 으로 처리 되면 자물쇠 가 잠 길 가능성 을 최소 화 할 수 있다.
        JDBC 프로 그래 밍 의 이상 한 문 제 를 어떻게 합 리 적 으로 처리 할 것 인 가 는 권위 있 는 책 들 도 만 족 스 러 운 답 을 내 놓 지 못 하고 있다.2003 년 전자 공업 출판사 에서 출판 한 미국 컴퓨터 보전 총서 인 라 는 책 에서 주요 장 에서 데이터 베 이 스 를 닫 고 연결 하 는 것 은 모두 catch 코드 블록 에서 이 루어 졌 으 며 마지막 24 장 에서 여러 차례 의 심 스 러 운 똑 같은 코드 가 나 왔 다.
        finally {
            if (con != null) {
                con.close();
            }
            if (stmt != null) {
                stmt.close();
            }
        }
        이 코드 에서
자원 을 닫 을 때 순서 오류 가 발생 했 습 니 다.
        (제7 판)하 권 제4 장 데이터베이스 프로 그래 밍 1 장 에서 데이터베이스 트 랜 잭 션 프로 그래 밍 에 관 한 이상 처리 코드 를 찾 을 수 없습니다.이 를 통 해 자바 계 는 JDBC 의 응용 개발 에 대해 깊이 있 는 연구 가 부족 하 다 는 것 을 알 수 있다.
        여러 개의 이상 처리 에 관 한 코드 는 대부분 아래 의 구조 에 따라 이 루어 진다.
        try {
        } catch (SQLException e) {
        } catch (IOException e) {
        } catch (XXXException e) {
        } finally {
        }

        데이터베이스 연결 사 무 를 열지 않 았 다 면 코드 는 다음 과 같 을 수 있 습 니 다.
        try {
            ...
        } catch (SQLException e) {
        } catch (IOException e) {
        } catch (XXXException e) {
        } finally {
            con.close()
        }
        이런 상황 에서 데이터베이스 에 자물쇠 가 생 길 가능성 은 제로 다.
        데이터베이스 연결 사 무 를 열 었 다 면 코드 는 다음 과 같 을 수 있 습 니 다.
        try {
            ...
            con.commit();
        } catch (SQLException e) {
            con.rollback();
        } catch (IOException e) {
        } catch (XXXException e) {
        } finally {
            con.close();
        }

       
이렇게 여러 가지 이상 이 혼 합 된 코드 중 비 SQLException 이상 이 발생 하면 잠 금 이 꺼 질 가능성 이 매우 높 으 며,비 SQLException 이상 이 발생 하면 업 무 를 제출 하지 도 않 았 고 스크롤 백 도 하지 않 았 다.JDBC 는 데이터베이스 연결 을 닫 았 지만 데이터베이스 서버 에 서 는 여전히 데이터베이스 업 무 를 열 었 다.SQL Server 2000 을 사용 할 때 이 점 은 SQL Server 2000 의 기업 관리자/관리/현재 활동/잠 금/대상 등 부분 을 관찰 하여 결론 을 얻 을 수 있다.다른 데이터베이스 제품 도 비슷 한 상황 이 있 습 니까?이 코드 는 우아 해 보이 지만 건장 성 이 부족 하 다.코드 의 건장 성 을 고려 하여 코드 를 세 개의 try{}catch(XXXException e){}finally{}로 나 누 어야 합 니 다.코드 의 우아 함 을 유지 하려 면 이 코드 의 실현 디 테 일 에 많은 노력 을 기울 여야 한다.예 를 들 어 boolean 변 수 를 몇 개 더 추가 하여 코드 가 다음 단계 까지 실 행 될 수 있 는 지 를 봐 야 한다.
        제 이 드 풀 은 이상 처리 에 상당 한 공 을 들 였 다.핵심 클래스 인 ProcessVO 에 서 는 DML 조작 과 관련 된 이상 이 모두 통합 되 어 SQLException 이상 을 일괄 적 으로 던 졌 다.예 를 들 어 삽입 을 실현 하 는 바 텀 핵심 코드 에서 모두 세 가지 유형의 이상 이 발생 했다.
        try{
          ...
        } catch (java.lang.ClassCastException ex) {
            throw new SQLException("java.lang.ClassCastException: " + ex.getMessage(), ex.getCause());
        } catch (NumberFormatException ex) {
            throw new SQLException("NumberFormatException: " + ex.getMessage(), ex.getCause());
        } catch (IOException ex) {
            throw new SQLException("IOException: " + ex.getMessage(), ex.getCause());
        } finally {
            pstmt.close();
        }
        관련 자원 을 열 고 닫 으 면 전체 ProcessVO 의 여러 방법 에 분산 되 지만 자원 을 닫 을 때 순 서 를 엄 격 히 주의 합 니 다.
데이터베이스 연결(또는 세 션),사무,Prepared Statement 대상,Statement 대상,ResultSet 대상 등 자원 에 대해 ProcessVO 에서 지 키 는 순 서 는 다음 과 같 습 니 다.
먼저 열 고,나중에 닫 고,나중에 열 고,먼저 닫 습 니 다.
        ProcessVO 에서 트 랜 잭 션 제출 을 실현 하 는 코드
    /**
     *     。
     *
     * @throws SQLException
     */
    public void commit() throws SQLException {
        if (!con.isClosed()) {
            if (!autoCommit) {
                try {
                    con.commit();
                    autoCommit = true;
                    con.setAutoCommit(autoCommit);
                    failCommit = false;
                    con.close();
                } finally {
                    if (failCommit) {
                        rollback();
                    }
                }
            }
        }
    }

        ProcessVO 에서 트 랜 잭 션 스크롤 백 을 실현 하 는 코드
    /**
     *     。
     *
     * @throws SQLException
     */
    public void rollback() throws SQLException {
        if (!con.isClosed()) {
            if (!this.autoCommit) {
                if (failCommit) {
                    if (savepoint == null) {
                        con.rollback();
                        con.close();
                        System.out.println("[" + dt.dateTime() + "] SQLServerException. Connection is already rollback and closed .");
                    } else {
                        con.rollback(savepoint);
                        con.close();
                        System.out.println("[" + dt.dateTime() + "] SQLServerException. Connection is already rollback at " + savepoint + " point and closed .");
                    }
                    autoCommit = true;
                }
            }
        }
    }

        ProcessVO 에서 데이터베이스 연결 이나 세 션 이라는 코드 를 닫 습 니 다.
    /**
     *        
     *
     * @throws SQLException
     */
    @Override
    public void closeCon() throws SQLException {
        try {
            /*
             * if (rs != null && !rs.isClosed()) { rs.close(); }
             *
             * if (stmt != null && !stmt.isClosed()) { stmt.close(); }
             */
        } finally {
            if (con != null && !con.isClosed()) {
                con.close();
            }
        }
    }


        ProcessVO 에서 종결 수비 자 모드 의 코드 를 더욱 보완 하 였 다.
     /**
     *      ,        ,    。                ,        ,             ,              。       ,             。<br/>
     * 1、      ;<br/> 2、        SQLException   ,             。<br/>
     */
    private final Object _finalizerGuardian = new Object() {
        @Override
        protected void finalize() throws SQLException, Throwable {
            if (con != null && !con.isClosed()) {
                try {
                    super.finalize();
                } finally {
                    if (!autoCommit) {
                        if (failCommit) {
                            try {
                                if (savepoint == null) {
                                    con.rollback();
                                } else {
                                    con.rollback(savepoint);
                                }
                                System.out.println("[" + dt.dateTime() + "] Connection rollback in finalize.");
                            } catch (SQLException ex) {
                                Logger.getLogger(ProcessVO.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
                            } finally {
                                con.close();
                                autoCommit = true;
                                System.out.println("[" + dt.dateTime() + "] Connection is not autocommit, rollback and then closed in finalize.");
                            }
                        } else {
                            con.close();
                            System.out.println("[" + dt.dateTime() + "] Connection is autocommit, closed in finalize,You should close it.");
                        }
                    } else {
                        con.close();
                        System.out.println("[" + dt.dateTime() + "] Connection closed in finalize,You should close it.");
                    }
                }
            }
        }
    };

        이 코드 들 은 SQLException 이 발생 하 는 전제 에서 트 랜 잭 션 을 열 면 트 랜 잭 션 이 다시 굴 러 가 는 지 확인 하고 세 션 을 닫 기 전에 트 랜 잭 션 을 닫 을 수 있 습 니 다.
        JadePool 이 발표 되 기 전에 이상 과 업무 의 제출,스크롤 백 간 의 관련 에 대해 대량의 테스트 를 실시 하여 JadePool 의 핵심 클래스 인 ProcessVO 가 건장 하고 신뢰 할 수 있 도록 확보 했다.
        여기
귀중 한 의견 을 제시 하여 제 가 JadePool 개원 프로젝트 를 더욱 잘 보완 할 수 있 도록 도와 주신 것 을 환영 합 니 다.실력 있 는 자바 일꾼 들 의 참 여 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기