Исключения в Java: как уменьшить повторяющийся код - PullRequest
0 голосов
/ 19 декабря 2018

Я использую шаблон объекта доступа к данным (DAO) в Java, и у меня один и тот же фрагмент кода, повторенный по всем моим файлам.Вот как-то так:

public User getById(int id) throws BDException {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
        query.setString("id", id);
        User user = (User) query.uniqueResult();
        tx.commit();

        return user;
    }
    catch(javax.validation.ConstraintViolationException | org.hibernate.exception.ConstraintViolationException cve) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw new BDException(cve);
    }
    catch(RuntimeException ex) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw ex;
    }
    catch(Exception ex) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw new RuntimeException(ex);
    }
}

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

Итак, есть ли решение повторно использовать код и не повторять (копировать-вставлять) код в каждом методе?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Похоже на задание для Выполнить вокруг идиомы .

Поместить специализированный код в лямбда-выражение.Передайте специализированный код методу с общим кодом, который выполняет объект, содержащий лямбда-выражение в соответствующей точке.

Для вашего кода, в зависимости от того, что именно вы хотите выделить, использование может выглядеть примерно так:

public User getById(int id) throws BDException {
    return query(
        "SELECT u FROM User u WHERE u.id=:id",
        query -> {
            query.setString("id", id);
            return (User) query.uniqueResult();
        }
    );
}
0 голосов
/ 19 декабря 2018

есть ли решение повторно использовать код и не повторять (копировать-вставлять) код в каждом методе?

.

"Мясо"вашей функции здесь

    Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
    query.setString("id", id);
    User user = (User) query.uniqueResult();

Если вы очень щурились, вы можете увидеть, что это «функция», которая принимает Session в качестве аргумента и возвращает User.Затем вы можете сделать эту функцию аргументом для функции, которая выполняет всю обработку исключений.

В Java это обычно означает выражение функции как «объекта»

User MyCrazyFunctionThing::uniqueResult(Session session) {
    Query query = session.createQuery(this.sql);
    query.setString("id", this.id);
    return query.uniqueResult();
}

User DatabaseGateway::execute(MyCrazyFunctionThing q) {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        User user = q.uniqueResult(session)
        tx.commit();

        return user;
    } catch (...) {
        // ...
    }
}

Сразу же вы можете превратить это в логику, которая может быть запущена в любое время, когда вы пытаетесь извлечь уникального пользователя из сеанса.

Вы можете сделать это еще более общим с помощью обобщений

interface MyCrazyGenericThing<T> {
    T uniqueResult(Session session);
}

class MyCrazyFunctionThing implements MyCrazyGenericThing<User> {
    User uniqueResult(Session session) {
        Query query = session.createQuery(this.sql);
        query.setString("id", this.id);
        return query.uniqueResult();
    }
}

<T> T DatabaseGateway::execute(MyCrazyGenericThing<T> q) {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        T result = q.uniqueResult(session)
        tx.commit();

        return result;
    } catch (...) {
        // ...
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...