Шаблон гибернации для повторного использования транзакции - PullRequest
1 голос
/ 19 октября 2011

У меня есть базовый метод, который я пишу, чтобы не повторять одну и ту же логику спящего режима / транзакции снова и снова.Это довольно просто, но есть конкретная проблема, которую, я не уверен, можно решить с помощью этого подхода.

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

Я сделал следующий метод, чтобы разрешить общие операции гибернации, которые могли бы работать с текущей транзакцией, если бы это было необходимо, хотя сейчасдумайте, что в его текущей форме это не будет работать, так как вызывает session.beginTransaction ();вероятно, вернет новую транзакцию, даже если предыдущая не была зафиксирована (это так?).Предположим, что я изменил его, чтобы он возвращал текущий сеанс и транзакцию, если было указано, что для текущей транзакции будет больше операций, как вы думаете, это будет работать?Было бы целесообразно сделать что-то подобное или вы бы порекомендовали изменить подход?Спасибо

protected <T> void baseOperation(Class<T> entityClass, List<T> instances, BaseHibernateDAO.Operations operation, boolean isLastOperation) throws Exception
{
    Session session = null;
    Transaction transaction = null;
    boolean caughtException = false;

    //get session from factory
    session = HibernateSessionFactory.getSession();

    try
    {
        //get current transaction
        transaction = session.beginTransaction();

        for (Object instance : instances) //perform operation on all instances
        {
            log.debug(String.format("Will perform %s operation on %s instance.", operation.name(), entityClass.getName()));

            switch (operation) //perform requested operation
            {
                case SAVE:
                    session.save(instance);
                    break;
                case UPDATE:
                    session.update(instance);
                    break;
                case SAVEORUPDATE:
                    session.saveOrUpdate(instance);
                    break;
                case DELETE:
                    session.saveOrUpdate(instance);
                    break;
            }

            log.debug(String.format("%s operation on %s instance was succesful.", operation.name(), entityClass.getName()));
        }

        session.flush(); //synchronize

        if (isLastOperation) //if this is the last operation of the transaction
        {
            transaction.commit();
            log.debug("Transaction commited succesfully.");
        }
    }
    catch (Exception e) //error occurred
    {
        caughtException = true;

        //roll-back if transaction exists
        if (transaction != null)
        {
            transaction.rollback();
        }

        //log and re-throw
        log.error("An error occurred during transaction operation.", e);
        throw e;
    }
    finally //cleanup tasks
    {
        if (isLastOperation || caughtException) //close session if there are no more pending operations or if an error occurred
        {
            HibernateSessionFactory.closeSession();
        }
    }
}

1 Ответ

7 голосов
/ 19 октября 2011

«Рекомендуется» - это прекращение попыток переписать код, который уже был написан, отлажен, перетянут в грязь, отлажен еще больше и развернут тысячи раз. Т.е. проблемы и соображения, с которыми вы сталкиваетесь, встречались и преодолевались ранее, и решения доказаны. Кроме того, поскольку они широко используются и улучшаются, они требуют гораздо меньших усилий, чем то, что вы вкладываете в свое собственное решение. Изучите поддержку Spring Hibernate , особенно "Внедрение DAO на основе простого API Hibernate 3" и " Декларативное разграничение транзакций ". Для дальнейшего чтения есть целая глава по управлению транзакциями .

У меня есть пример проекта на github , где вы можете увидеть очень простой пример использования Spring для управления сеансами и транзакциями Hibernate в контексте веб-приложения (с использованием Spring MVC).

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

Существует три основных способа использования обработки транзакций Spring: декларативно , определяющий, какие методы являются транзакционными с XML , декларативно , аннотирующие методы как @ Transactional или программно с использованием TransactionTemplate .

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