Java - извлечение больших объемов данных из БД с использованием iBatis - PullRequest
2 голосов
/ 28 августа 2009

Мне нужно извлечь данные из таблицы DB2, выполнить некоторую обработку каждой возвращенной строки и вывести ее в плоский файл. Я использую iBatis, но обнаружил, что с помощью queryForList я начал получать ошибки памяти, я буду смотреть на увеличение 100k + строк данных.

Я смотрел на использование queryWithRowHandler вместо этого, но интерфейс iBatis RowHandler не выдает исключение из его handleRow функция, поэтому, если она получает ошибку, я не могу правильно сообщить об этом и прекратить итерации остальных данных. Похоже, я могу создать исключение RuntimeException, но это не кажется мне изящным способом ведения дел.

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

Кто-нибудь имел опыт работы с этим подходом или имел альтернативное решение с использованием iBatis. Я знаю, что мог бы сделать это без iBatis, просто используя JDBC, но, поскольку iBatis используется для всех других видов доступа к БД в моем приложении, я хотел бы использовать эту архитектуру, если это возможно.

1 Ответ

3 голосов
/ 28 августа 2009

1) Создайте свой собственный интерфейс RowHandler с отмеченными исключениями в подписи:

public interface MySpecialRowHandler {
    public void handleRow(Object row) 
        throws DataException, FileException, WhateverException;
}

2) Унаследуйте (или, что еще лучше, делегат ) от SqlMapDaoTemplate, чтобы добавить новый метод, который будет управлять вашим собственным обработчиком с такими же исключениями в подписи:

public class MySpecialTemplate extends SqlMapDaoTemplate {
    ...
    public void queryWithRowHandler(String id, 
        final MySpecialRowHandler myRowHandler
    ) throws DataException, FileException, WhateverException {
        // "holder" will hold the exception thrown by your special rowHandler
        // both "holder" and "myRowHandler" need to be declared as "final"
        final Set<Exception> holder = new HashSet<Exception>();
        this.queryWithRowHandler(id,new RowHandler() {
            public void handleRow(Object row) {
                try {
                    // your own row handler is executed in IBatis row handler
                    myRowHandler.handleRow(row);
                } catch (Exception e) {
                    holder.add(e);
                }
            }
        });
        // if an exception was thrown, rethrow it.
        if (!holder.isEmpty()) {
            Exception e = holder.iterator().next();
            if (e instanceof DataException)     throw (DataException)e;
            if (e instanceof FileException)     throw (FileException)e;
            if (e instanceof WhateverException) throw (WhateverException)e;
            // You'll need this, in case none of the above works
            throw (RuntimeException)e;
        }
    }
}                    

3) Ваш бизнес-код будет выглядеть так:

// create your rowHandler
public class Db2RowHandler implements MySpecialRowHandler {
    void handleRow(Object row) throws DataException, FileException, WhateverException {
        // what you would have done in ibatis RowHandler, with your own exceptions
    }
}
// use it.
MySpecialTemplate template = new MySpecialTemplate(daoManager);
try {
    template.queryWithRowHandler("selectAllDb2", new Db2RowHandler());
} catch (DataException e) {
    // ...
} catch (FileException e) {
    ...
...