Реализовать разбиение на страницы с использованием смещения в java jdbc

Я пытаюсь реализовать разбиение на страницы с помощью java jdbc. Мой запрос принимает ограничение, которое представляет собой размер пакета и смещение.

Как увеличить смещение после завершения каждой партии. Я не могу понять, как я могу использовать это смещение для достижения функциональности. Я попытался написать метод-оболочку, который рекурсивно вызывает метод, принимающий смещение.

Вот мой запрос

select
ECId,InvId,ApplianceId,ProgName,CollectStartTS,CollectEndTS,CRPartyId,
HostName,IPAddess,SoftwareVer,OsType,collectserialnum,
CollectProductId,SNMPLoc,HWAlertCnt,SWAlertCnt,UploadProcEndTS
from inventory_details

и код

public void getInventory() throws SQLException {
    int batch = Integer.parseInt(PropertyFileReader.getInstance()
         .getProperty("BATCHSIZE"));
    int offset= 0;
    while(offset<batch){
        DrillDAO dao = new DrillDAO();
        dao.getAllInventoryDetails(offset); 
    }   
    offset = offset+batch+1;
}

public ArrayList<InventoryDetail> getAllInventoryDetails(int offset)
             throws SQLException {              
    int batchSize = Integer.parseInt(PropertyFileReader.getInstance()
                    .getProperty("BATCHSIZE"));             

    ArrayList<InventoryDetail> inventoryDetailList = new ArrayList<InventoryDetail>();              

    Connection connection = null;
    Statement statement = null;
    ResultSet resultset = null;
    try {
        Class.forName(getJdbcDriver());
        connection = DriverManager.getConnection(
                     getJdbcURL(), getUserName(), getPassword());
        statement = connection.createStatement();
        LOGGER.info("Start time    " + CPUUtils.getCpuTime());
        resultset = statement.executeQuery(getQuery() 
                  + " " + "LIMIT" + " " + batchSize + " " 
                  + "OFFSET" + " " + offset);
        LOGGER.info("End time    " + CPUUtils.getCpuTime());

        while (resultset.next()) {
            InventoryDetail id = new InventoryDetail();
            id.setEcId(resultset.getString(1));
            id.setInvId(resultset.getString(2));
            id.setApplianceId(resultset.getString(3));
            id.setProgName(resultset.getString(4));
            id.setCollectStartTS(resultset.getString(5));
            id.setCollectEndTS(resultset.getString(6));
            id.setCrPartyId(resultset.getString(7));
            id.setHostName(resultset.getString(8));
            id.setIpAddess(resultset.getString(9));
            id.setSoftwareVer(resultset.getString(10));
            id.setOsType(resultset.getString(11));
            id.setCollectSerialNum(resultset.getString(12));
            id.setCollectProductId(resultset.getString(13));
            id.setSnmpLoc(resultset.getString(14));
            id.setHwAlertCnt(resultset.getString(15));
            id.setSwAlertCnt(resultset.getString(16));
            id.setUploadProcEndTS(resultset.getString(17));
            inventoryDetailList.add(id);
        }
    } catch (SQLException se) {
        se.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (statement != null)
                statement.close();
        } catch (SQLException se2) {
        }
        try {
            if (connection != null)
                connection.close();
        } catch (SQLException se) {
           se.printStackTrace();
        }
    }  
    return inventoryDetailList;
}

person Community    schedule 31.01.2017    source источник
comment
Пагинация не имеет смысла, если вы не укажете какой-либо порядок для набора результатов, то есть объявите ORDER BY в запросе. Как следует расположить ряды?   -  person Mick Mnemonic    schedule 01.02.2017


Ответы (2)


Вы можете написать обертку, как показано ниже:

public List<InventoryDetail> getInventory() throws SQLException {
        int batch = Integer.parseInt(PropertyFileReader.getInstance().getProperty("BATCHSIZE"));
        int offset= 0;

        List<InventoryDetail> finalList = new ArrayList<InventoryDetail>();

        DrillDAO dao = new DrillDAO();
        for(int i = offset; ; i += batch+1) {
            //request data with one more, if exact that count return, you will know more data exist
            //so you can continue; when less than that return, you will know no more data, so break the loop
            ArrayList<InventoryDetail> invList = dao.getAllInventoryDetails(i, batch + 1);            
            if (invList.size() <= batch) {                
                break;
            } else {
                //remove the extra one called cz it will get in next call
                invList.remove(invList.size() - 1);                
            }
            finalList.addAll(invList);
        }

        return finalList;
    }

Изменять

public ArrayList<InventoryDetail> getAllInventoryDetails(int offset)
            throws SQLException {

to

public ArrayList<InventoryDetail> getAllInventoryDetails(int offset, int batchSize)
            throws SQLException {

и удалите внутри него следующую строку.

int batchSize = Integer.parseInt(PropertyFileReader.getInstance()
                    .getProperty("BATCHSIZE"));  
person Monzurul Haque Shimul    schedule 01.02.2017

Во-первых, вы должны подсчитать ваш SELECT:

String countQuery = "SELECT COUNT(0)\n" +
    "FROM INVENTORY_DETAILS";

Теперь, когда у вас есть размер результата, спросите, больше ли он 0, таким образом вам не придется выполнять исходный запрос ни за что:

// here goes the statement declaration and execution
long count = statement.execute(countQuery);
List<InventoryDetail> inventoryDetailList = new ArrayList<InventoryDetail>();

if (count > 0) {
    String query = "SELECT ECID,INVID,APPLIANCEID,PROGNAME,COLLECTSTARTTS,COLLECTENDTS,CRPARTYID,\n" +
        "    HOSTNAME,IPADDESS,SOFTWAREVER,OSTYPE,COLLECTSERIALNUM,\n" +
        "    COLLECTPRODUCTID,SNMPLOC,HWALERTCNT,SWALERTCNT,UPLOADPROCENDTS\n"+
        "FROM INVENTORY_DETAILS\n";

Наконец, и это самая важная часть инструкции, вы будете повторять разбиение на страницы:

    long page = 1;
    long limit = page * offset;
    long loops = (count - (count % limit)) / offset;

    for (; page <= loops; page++) {
        if (page == 1) {
            query += "LIMIT " + limit;
        } else {
            limit = page * offset;
            query += "LIMIT " + limit + " OFFSET " + offset;
        }

        // here goes the statement declaration and execution
        statement.execute(query);
        // here goes the result set iteration and then...
        inventoryDetailList.add(id);
    }
}

Надеюсь, это поможет.

person Gabriel Villacis    schedule 01.02.2017
comment
Поскольку в запросе не указан порядок строк, ничто не гарантирует, что одна и та же строка не появится более чем на одной странице. - person Mick Mnemonic; 02.02.2017
comment
Да, я знаю, но этот король реализации требует большего объяснения и большей сложности для добавления, потому что он требует динамической разбивки на страницы в зависимости от некоторого поля, добавленного в порядок строк. Мое намерение здесь было просто дать подсказку, как реализовать простую разбивку на страницы. Любой может проверить это реализация из проекта Spring, которая объясняет мой предыдущий комментарий. - person Gabriel Villacis; 02.02.2017