복붙노트

[SQL] JDBC 매김

SQL

JDBC 매김

나는 JDBC를 사용하여 페이지 매김을 구현하고자합니다. 내가 알고 싶은 실제 것은 "내가 어떻게 각각 페이지 1 2 다음 데이터베이스에서 향후 50 기록을 처음 50을 얻을 수 있습니다"입니다

내 쿼리 데이터에서 선택 *이다 데이터 테이블은 20,000 행을 포함]

페이지 # 1을 위해 나는 50 개 기록을 얻을 페이지 # 2 나는 50 개 기록 옆에 싶어. 어떻게 JDBC에 효율적으로 구현할 수있다?

내가 검색 한 rs.absolute (행) 첫 페이지 기록을 생략 할 수있는 방법이라는 것을 발견하지만 큰 결과 세트에 어느 정도의 시간을 소요하고 나는이 시간을 부담하지 않으려했다. 또한, 나는, 나는 아직도 내가 쿼리를 사용하지 않는 이유, 잘 모릅니다이 쿼리에 사용하기 좋은하지 않기 때문에 쿼리의 오프셋 (offset) ROWNUM 및 제한 +를 사용하지 않습니다.

캔 사람의 도움을 내게하는 방법은 페이지 매기기에의 ResultSet을 제한 받거나 JDBC이 우리에게주고있는 방법은 무엇입니까?

해결법

  1. ==============================

    1.단순히 JDBC를 사용하여이 일을 더 효율적인 방법이 없습니다. 당신은 n 행에 제한을 공식화하고 효율적으로하기위한 SQL에 직접 i 번째의 항목 절을 시작해야합니다. (MySQL의의 LIMIT의 개의 키워드 참조)이 힘이 사실은 꽤 쉽게 데이터베이스에 따라 Oracle과 같은 다른 데이터베이스에 조금 난이도가 될 수 있습니다 (하위 쿼리 및 사용 ROWNUM 의사 열을 포함한다).

    단순히 JDBC를 사용하여이 일을 더 효율적인 방법이 없습니다. 당신은 n 행에 제한을 공식화하고 효율적으로하기위한 SQL에 직접 i 번째의 항목 절을 시작해야합니다. (MySQL의의 LIMIT의 개의 키워드 참조)이 힘이 사실은 꽤 쉽게 데이터베이스에 따라 Oracle과 같은 다른 데이터베이스에 조금 난이도가 될 수 있습니다 (하위 쿼리 및 사용 ROWNUM 의사 열을 포함한다).

    이 JDBC 매김 자습서를 참조하십시오 : http://java.avdiel.com/Tutorials/JDBCPaging.html

  2. ==============================

    2.당신은 데이터 만 실제로 현재 페이지에 표시 할 필요를 조회한다. 자바의 메모리에 전체 데이터 집합을 운반하고 거기를 필터링하지 않음. 그것은 단지 불필요하게 느린 물건을 만들 것입니다.

    당신은 데이터 만 실제로 현재 페이지에 표시 할 필요를 조회한다. 자바의 메모리에 전체 데이터 집합을 운반하고 거기를 필터링하지 않음. 그것은 단지 불필요하게 느린 물건을 만들 것입니다.

    당신이 실제로 제대로이 구현 및 / 또는 특정 데이터베이스에 대한 SQL 쿼리를 계산에 어려움이있는 경우, 여기에 내 대답을 살펴 있습니다.

    업데이트 : Oracle을 사용하고 있기 때문에, 여기에 상기 대답에서 오라클 대상 추출물이다 :

  3. ==============================

    3.면책 조항 : SQL 페이지 매김 및 JDBC 페이지 매김에이 블로그 게시물은 나에 의해 게시됩니다.

    면책 조항 : SQL 페이지 매김 및 JDBC 페이지 매김에이 블로그 게시물은 나에 의해 게시됩니다.

    최대 절전 모드 매김을 무시하고, 우리는 SQL 매김 / JDBC 매김 사용할 수 있습니다

    SQL 페이지 매김

    두 가지 기본 방법이 있습니다 :

    그것을 할 방법은 SQL 고유의 것입니다

    MySQL은 / ​​다른 많은 SQL을 위해 그것은 제한하여 수행하고 상쇄 될 수 있습니다

    PostgreSQL을 : http://microjet.ath.cx/WebWiki/ResultPaginationWithPostgresql.html

    오라클에서는 핸들 "최고-N 쿼리"예를 들어,에 같은 양식을 사용 최적화 된 5 가장 높은 유료 직원, 누구

    select *   from ( select a.*, rownum rnum
    
    from ( YOUR_QUERY_GOES_HERE -- including the order by ) a
    
    where rownum <= MAX_ROWS )
    
    where rnum >= MIN_ROWS
    

    여기 ROW-NUM에 아주 자세한 설명입니다

    유사 SO 스레드

    JDBC 매김

    마음에 와서 질문 : 제가 SQL을 실행할 때, 어떻게 결과가로드되는? 즉시 또는 요청에? 이 SO 스레드와 동일

    먼저 우리는 오라클로, JDBC의 몇 가지 기본을 이해할 필요가있다

    javadoc의 별 :의 Statement.execute ()

    execute: Returns true if the first object that the query returns is a ResultSet object. Use this method if the query could return one or more ResultSet objects. Retrieve the ResultSet objects returned from the query by repeatedly calling Statement.getResutSet.
    

    우리는 커서를 통해 결과 집합의 데이터에 액세스 할 수 있습니다. 그것은 처음에 데이터의 첫 번째 행 앞에 위치 포인터 동안이 커서 DB 다르다 있습니다.

    데이터는 요청에 가져올 수 있습니다. 당신이 할 때 실행하는 동안 ()를 처음으로 가져 오는 있습니다.

    그런 다음, 얼마나 많은 데이터가로드? 그것은 구성 할 수 있습니다.  하나는 DB에서 드라이버, 그것은 한 번에 검색하는 방법 큰 블록으로 한 번에 가져올 얼마나 많은 행 제어의 ResultSet의 자바 API의의 setFetchSize () 메서드를 사용할 수 있습니다.

    예를 들어 메모리에로드 될 것입니다 또 다른 100 개의 행을 행 101 지역 memory.to 쿼리에서로드됩니다 100 DB에서 행과 100 행으로 2 위를로드 할 첫 번째 행을 가져 오는, 크기는 100 가져 오는 경우 전체 결과는 1000입니다 가정합니다.

    의 JavaDoc에서

    Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are needed for ResultSet objects genrated by this Statement. If the value specified is zero, then the hint is ignored. The default value is zero.
    

    단어 "힌트"를 참고 -이 드라이버 특정 구현에 의해 무시 될 수 있습니다.

    이것은 SQL 개발자와 같은 클라이언트 기능은 "100로 제한 행은"기반에도 효과가있을 것이다.

    스크롤 결과 전체 솔루션을 완료하면, 하나 개의 필요 API의 결과 집합 유형 및 화면 이동 커서를 고려

    하나는 오라클이 게시물에 들어있는 예제 구현을 찾을 수 있습니다

    책 오라클 상단 링크 개발자 가이드에서 이는 예 112 JDBC 드라이버 반입 크기

    ReadAllQuery query = new ReadAllQuery();
    
    query.setReferenceClass(Employee.class);
    
    query.setSelectionCriteria(new ExpressionBuilder.get("id").greaterThan(100));
    
    // Set the JDBC fetch size
    
    query.setFetchSize(50);
    
    // Configure the query to return results as a ScrollableCursor
    
    query.useScrollableCursor();
    
    // Execute the query
    
    ScrollableCursor cursor = (ScrollableCursor) session.executeQuery(query);
    
    // Iterate over the results
    
    while (cursor.hasNext()) {
    
    System.out.println(cursor.next().toString());
    
    }
    
    cursor.close();
    

    .....................

    결국, 질문에 종기

    페이지 매김을 할 수있는 더 좋은 방법은 무엇입니까?

    는 SQL은 SQL 접근 방식에서 메이크업 감각에 의해 주문해야합니다

    그렇지 않으면 다음 페이지에서 다시 일부 행을 표시 할 수 있습니다.

    다음은 JDBC 드라이버 및 기타 SO의 답변에 PostgreSQL을 설명서에서 몇 가지 포인트입니다

    첫째, 원래 쿼리는 합리적으로 페이징 솔루션 작동 할 수 있도록하기 위해 ORDER BY 절을해야합니다. 오라클은 첫 번째 페이지, 두 번째 페이지 및 N 번째 페이지에 대해 같은 500 개 행을 반환 할 그렇지 않으면, 그것은 완벽하게 유효 할 것

    주요 차이점은 가져 오는 동안 접속을 유지하는데 필요하다 JDBC 방법입니다. 이것은 예를 들어, 비 저장 웹 응용 프로그램에 적합하지 않을 수 있습니다.

    SQL의 방법을

    구문은 SQL 고유의 것입니다 및 유지 관리가 용이하지 않을 수있다. JDBC의 방법을

    일부 추가 읽기

    이 포스팅은 광학 페치 사이즈와 성능 조정에 관한 것입니다

  4. ==============================

    4.나는이 질문은 오래 알고,하지만 난 페이징을 구현하는 방법이있다, 나는 누군가가 도움이되기를 바랍니다

    나는이 질문은 오래 알고,하지만 난 페이징을 구현하는 방법이있다, 나는 누군가가 도움이되기를 바랍니다

    int pageNo = ....;    
    String query = "SELECT * FROM data LIMIT ";
    
    switch (pageNo) {
    case 0: // no pagination, get all rows
        query += Integer.MAX_VALUE; // a big value to get all rows
        break;
    case 1: // get 1st page i.e 50 rows
        query += 50;
        break;
    default:
        query += String.valueOf((pageNo-1)*50 + 1) ", " + String.valueOf(50);
        break;
    }
    
    PreparedStatement ps = connection.prepareStatement(query);
    ....
    

    그것은 임의의 수를 변경할 수 있도록 값 pageSize가 50라는 일정 할

  5. ==============================

    5.당신은 MySQL의 또는 PostgreSQL의 한계를 사용하여 오프셋하는 경우 귀하의 키워드입니다. MSSQLSERVER와 오라클은 유사한 기능을 가지고,하지만 난 좀 더 고통스러운 것 같다.

    당신은 MySQL의 또는 PostgreSQL의 한계를 사용하여 오프셋하는 경우 귀하의 키워드입니다. MSSQLSERVER와 오라클은 유사한 기능을 가지고,하지만 난 좀 더 고통스러운 것 같다.

    MySQL과 PostgreSQL을 여기를 보라 :

    http://www.petefreitag.com/item/451.cfm

    오라클은 여기를 보라 :

    http://www.oracle-base.com/forums/viewtopic.php?f=2&t=8635

  6. ==============================

    6.이 paginating 결과에 대한 최대 절전 모드 솔루션에 대한 링크입니다 : HQL - 페이지 매김을위한 행 식별자

    이 paginating 결과에 대한 최대 절전 모드 솔루션에 대한 링크입니다 : HQL - 페이지 매김을위한 행 식별자

  7. ==============================

    7.난 당신이 JDBC 연결이 필요한 때 매우 긴 시간과 탐색을 위해 열어 둘 하나의 거대한 결과 집합을 갖고 싶어하지 않는 것이 암묵적으로 이해합니다.

    난 당신이 JDBC 연결이 필요한 때 매우 긴 시간과 탐색을 위해 열어 둘 하나의 거대한 결과 집합을 갖고 싶어하지 않는 것이 암묵적으로 이해합니다.

    일반적인 접근 방식은 불행하게도 데이터베이스에 대한 데이터베이스와 다른 전체 요청의 하위 집합을 얻기 위해 필요한 SQL을 추가하고 SQL 문 공급 업체 특정 만들 것입니다. 내가 올바르게 기억, LIMIT는 MySQL과 연동하여 사용됩니다. 모든 요청에 ​​대한 적절한 범위에 대한 질문.

    또한 Hibernate는 당신이 HQL이 작업을 수행 할 수있는 기능이 포함되어 있다고 생각하지만 난 그게 익숙하지 않은입니다.

  8. ==============================

    8.당신은 최대 절전 모드 또는 자바 퍼시스턴스 API 또는 그냥 일반 SQL과 같은 ORM 프레임 워크의 어떤 종류를 사용하고 있습니까?

    당신은 최대 절전 모드 또는 자바 퍼시스턴스 API 또는 그냥 일반 SQL과 같은 ORM 프레임 워크의 어떤 종류를 사용하고 있습니까?

    다음 답변 내 : 사용 LIMIT와 OFFSET http://www.petefreitag.com/item/451.cfm

    또는 ROWNUM 연산자를 통해 이동 그런 다음 SQL 래퍼 필요하지만, 기본적으로이다

      select * from (select bla.*, ROWNUM rn from (
      <your sql here>
      ) bla where rownum < 200) where rn >= 150'
    
  9. ==============================

    9.당신이 사용할 수 있도록 오라클은 8i를 이후 표준 ROW_NUMBER () 윈도우 기능을 지원합니다. 당신은 단지 시작과 끝 행 번호를 설정해야합니다, 그래서 당신은 매개 변수가있는 쿼리로 할 수 있습니다. 예를 들면

    당신이 사용할 수 있도록 오라클은 8i를 이후 표준 ROW_NUMBER () 윈도우 기능을 지원합니다. 당신은 단지 시작과 끝 행 번호를 설정해야합니다, 그래서 당신은 매개 변수가있는 쿼리로 할 수 있습니다. 예를 들면

    SELECT * 
       FROM ( SELECT *, ROW_NUMBER() ORDER BY (sort key) AS rowNumber FROM <your table name> ) AS data
    WHERE 
       rowNumber>=:start AND
       rowNumber<:end
    

    (당신이 명명 된 매개 변수를 사용하지 않는이, 교체하는 경우 : 시작 / : 위치 매개 변수 자리 표시 자와 끝 '을?')

    참조 SELECT SQL, 위키 피 디아에 창 기능. 이 기사는 또한 ROW_NUMBER () 표준 윈도우 기능을 지원하는 다른 데시벨을 보여줍니다.

  10. ==============================

    10.

    PreparedStatement pStmt = // ... however you make it
    pStmt.setFetchSize( /* desired number of records to get into memory */ ); 
    

    참고의 setFetchSize (INT)는 단지 힌트 - 내가 예를 들어 MySQL과 그것을 사용했다 마지막으로, 그것은 지원되지 않습니다. 자신의 JDBC는 그것을 지원하는 것처럼 Oracle 문서에서 잠시 둘러보고, 그것은 보인다. 나는 그 날을 인용하지,하지만 그것은 가치가 적어도하려고; 그래,이 답변이 취약하지만 강력한 솔루션을 구현하는 것보다 충분히 덜 두통이있을 수 있습니다.

    기본적으로, 당신은 모든 요청을 발행 할 수 있습니다, 그리고 당신 만이 (이전 결과에 보유하지 않는 제공) 한 번에 메모리에 반입 크기를 얻을. 당신이 당신이, 50 사이즈를 가져 연결 / 쿼리을 설정할 것 그래서, 처음 50 개합니다 (또 다른 쿼리의 다음 물린 가져 원인) 결과 등을 표시합니다.

  11. ==============================

    11.입력:

    입력:

    결과:

    단지 쿼리를위한 이점 :

    불리:

  12. ==============================

    12.당신은이에 대한 방법을 아래에 사용할 수 있습니다.

    당신은이에 대한 방법을 아래에 사용할 수 있습니다.

    
    
         public CachedRowSet getScrollableList(PreparedStatement prestmt, int rowNo)
                    {   
                        getPageSize();
                        ResultSet rs = null;
                        CachedRowSet crs = null;
                        try
                        {           
                            rs = prestmt.executeQuery();
                            crs = new CachedRowSetImpl();
                            crs.setPageSize(pageSize);
                            crs.populate(rs, rowNo);
                        }
                        catch (SQLException ex)
                        {
                            logger.error("Exception in DatabaseInterface in getScrollableList() method: "+ ex.getMessage(),ex);
                        }   
                        finally
                        {
                            //close rs
                            //close pstmt
                        }
                        return crs;
                    }
    
    
    
     
  13. ==============================

    13.자바 코드를 잘 작동합니다 다음 :

    자바 코드를 잘 작동합니다 다음 :

    package paginationSample;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /**
     *
     * @ Nwaeze Emmanuel (FUNAI, 2016)
     */
    public class PaginationSample extends javax.swing.JFrame {  
    public void getRows() {
    Connection con2;
    Statement stmt2;
    ResultSet rs2;
    int j=0;
    String sz="";
    
      try {
    // Load MS accces driver class
     Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 
    String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, 
      *.accdb)};DBQ=" + "C:\\Database2.mdb"; 
    try{
    con2 = DriverManager.getConnection(url, "user", "");
    System.out.println("Connection Succesfull");
    
     try{
       stmt2=con2.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
       ResultSet.CONCUR_UPDATABLE );
       String sql="";
    
       if (txtpage.getText().trim().equals("") || 
          txtpagesize.getText().trim().equals("")){
    
        }else{
         int pagesize=Integer.parseInt(txtpagesize.getText());   
         int page=Integer.parseInt(txtpage.getText());
         sql="SELECT * FROM FSRegistration100L WHERE SN >= " +  
        (pagesize*page-pagesize+1) + " AND " + "SN <= " + (pagesize*page);
         rs2=stmt2.executeQuery(sql);
         if (rs2.wasNull()){
    
         }else{
           while ( rs2.next()){
             sz=sz + rs2.getString("RegNo") + "\n";
    
              j++;  
    
            }
           txta.setText(sz);
           txta.append(" Total rows =" + Integer.toString(j));
        } 
        }
          stmt2.close();
          con2.close();
      }
      catch (NullPointerException s){
      System.err.println("Got an exception166! ");
      System.out.println(s.getMessage());
      } 
     } catch (SQLException e1) {
    System.err.println("Got an exception1! ");
    System.err.println(e1.getMessage());
    }
    } catch (ClassNotFoundException e2) {
    System.err.println("Got an exception2! ");
    System.err.println(e2.getMessage());
    
    } 
    }
    
    
    
        private void jButton1ActionPerformed(java.awt.event.ActionEvent 
           evt)     {                                         
           // TODO add your handling code here:
            getRows();
        }                                        
    
        // Variables declaration - do not modify                     
        private javax.swing.JButton jButton1;
        private javax.swing.JLabel jLabel1;
        private javax.swing.JLabel jLabel2;
        private javax.swing.JScrollPane jScrollPane1;
        private javax.swing.JTextArea txta;
        private javax.swing.JTextField txtpage;
        private javax.swing.JTextField txtpagesize;
        // End of variables declaration 
    
  14. from https://stackoverflow.com/questions/2771439/jdbc-pagination by cc-by-sa and MIT license