Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > hibernate запрос


Автор: SuperFly 21.11.2007, 18:37
Еще раз, здравствуйте.

Хотел узнать, как вы реализуете в JPA  или Hibernate по 1 сессии на запрос?
Есть стандартные решения или каждый делает своё?

Автор: SuperFly 22.11.2007, 15:04
Видмо, я что-то не так спросил? Тема обсуждалась?

Автор: iluvatar 22.11.2007, 18:06
  ну, у меня 1 метод=1 запрос = 1 сессия

Автор: SuperFly 22.11.2007, 19:16
Хм, я думаю этот вариант весьма жесткий.

Представьте, над 1 проектом работают несколько программистов, я сомневаюсь, что они 1 методом договорятся. Необходим последовательный доступ к сессии из разных участков проекта (громко сказал, но учебный-проект тоже проект).

Автор: skhilkov 23.11.2007, 07:30
SuperFly
используй пул соединений, например http://commons.apache.org/dbcp/

Добавлено @ 07:35
Цитата(SuperFly @ 22.11.2007,  19:16)
Представьте, над 1 проектом работают несколько программистов, я сомневаюсь, что они 1 методом договорятся. Необходим последовательный доступ к сессии из разных участков проекта (громко сказал, но учебный-проект тоже проект).

а что мешает создать еще сессию? по-моему, мы говорим о разных вещах...

Автор: iluvatar 23.11.2007, 10:36
Цитата(skhilkov @  23.11.2007,  07:30 Найти цитируемый пост)

Цитата(SuperFly @ 22.11.2007,  19:16)
Представьте, над 1 проектом работают несколько программистов, я сомневаюсь, что они 1 методом договорятся. Необходим последовательный доступ к сессии из разных участков проекта (громко сказал, но учебный-проект тоже проект).

а что мешает создать еще сессию? по-моему, мы говорим о разных вещах...

я что-то тоже не понял.

Я тоже работаю в команде. И проблем не вижу. Делай метод, в который передаются все параметры, в зависимости от которых генерится запрос. создаешь сессию, выполняешь запрос, закрываешь сессию. Что здесь неправильно?

Автор: skhilkov 23.11.2007, 12:25
SuperFly,  а ты не путаешь, случаем, сессию и соединение?

Автор: SuperFly 23.11.2007, 13:15
skhilkov, Ууупс, конечно путаю!

Добавлено через 1 минуту и 4 секунды
Вообще неправильно все сказал :(

Под запросом, имею ввиду запрос пользователя.
Под сессией, всё таки как правильно заметили имею ввиду соединение.

Добавлено через 2 минуты и 8 секунд
Да, прошу прощения, совсем себя запутал.

Добавлено через 8 минут и 48 секунд
Я бы +1 поставил skhilkov, за наблюдательность.

Автор: Kangaroo 23.11.2007, 22:48
Цитата(SuperFly @  23.11.2007,  12:15 Найти цитируемый пост)
Да, прошу прощения, совсем себя запутал.

Я так понимаю, вопрос снят?

Цитата(SuperFly @  23.11.2007,  12:15 Найти цитируемый пост)
Я бы +1 поставил skhilkov, за наблюдательность. 

Сейчас поставим ;)

Автор: SuperFly 15.1.2008, 14:23
Цитата(Kangaroo @  23.11.2007,  22:48 Найти цитируемый пост)
Я так понимаю, вопрос снят?

Хыыы, всё таки оказалось, что вопрос не снят!

Я нашел то что задумал:

Код

public class HibernateUtil {
    private static SessionFactory factory;
    private static AnnotationConfiguration aconf = new AnnotationConfiguration();
    private static final ThreadLocal threadSession = new ThreadLocal();
    private static final ThreadLocal threadTransaction = new ThreadLocal();

    public static Session getSession() {
        Session s = (Session) threadSession.get();
        if (s == null) {
            s = factory.openSession();
            threadSession.set(s);
        }
        return s;
    }

    public static void closeSession() {
        try {
            Session s = (Session) threadSession.get();
            threadSession.set(null);
            if (s != null && s.isOpen())
                s.close();
        } catch (HibernateException ex) {
            ex.printStackTrace();
        }
    }

    public static void beginTransaction() {
        Transaction tx = (Transaction) threadTransaction.get();
        try {
            if (tx == null) {
                tx = getSession().beginTransaction();
                threadTransaction.set(tx);
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        }
    }

    public static void commitTransaction() {
        Transaction tx = (Transaction) threadTransaction.get();
        try {
            if (tx != null && !tx.wasCommitted()
                    && !tx.wasRolledBack())
                tx.commit();
            threadTransaction.set(null);
        } catch (HibernateException ex) {
            rollbackTransaction();
            ex.printStackTrace();
        }
    }

    public static void rollbackTransaction() {
        Transaction tx = (Transaction) threadTransaction.get();
        try {
            threadTransaction.set(null);
            if (tx != null && !tx.wasCommitted()
                    && !tx.wasRolledBack()) {
                tx.rollback();
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        } finally {
            closeSession();
        }
    }

    public static void addClass(Class<?> className) {
        aconf.addAnnotatedClass(className);
    }

    public static void load() {
        Configuration conf = aconf.configure();
        factory = conf.buildSessionFactory();
    }

    public static void addPackage(String pack) {
        aconf.addPackage(pack);
    }
}


Чудесное свойство ThreadLocal!!!

Ну и встал вопрос как мне стартовать транзакцию и коммитировать или роллбечить?
У меня дума сделать фильтр:

Код

public class HibernateFilter implements javax.servlet.Filter {

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HibernateUtil.beginTransaction();
        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {
        HibernateUtil.commitTransaction();
        HibernateUtil.closeSession();
    }
}


Но, тут проблемка с роллбеком, где я должен его обрабатывать?

Автор: Greg 18.1.2008, 17:00
Оборачивать каждый пользовательский запрос в транзакцию - неправильно. Даже если фильтр применяется не ко всем запросам - тоже неправильно. Создавать транзакцию нужно в классе, где реализуется работа с базой данных, там же фиксировать (commit) или откатывать (rollback). Настоятельно рекомендую читать про паттерн DAO  (Data Access Object) и смотреть примеры.

Автор: Platon 22.1.2008, 12:33
...

Автор: Greg 3.2.2008, 14:54
Цитата(SuperFly @  21.11.2007,  18:37 Найти цитируемый пост)
Хотел узнать, как вы реализуете в JPA  или Hibernate по 1 сессии на запрос?
Есть стандартные решения или каждый делает своё?

Можно использовать реализацию паттерна Open Session In View из Spring framework - она инкапсулируется в фильтре org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.
Реализация паттерна привязывает объект org.hibernate.Session, к треду, в котором выполняется пользовательский запрос. Таким образом во время обработки пользовательского запроса разработчику не нужно заботиться о создании или освобождении сессии.

Автор: SuperFly 3.2.2008, 14:59
Как понять моё цитирование? Теперь сами столкнулись с такой проблемой? Но, вы же сами предложили некое решение.

Автор: Greg 3.2.2008, 15:11
В предыдущем сообщении я говорил про транзакции, потому что из Вашего примера они создаются раньше чем требуется. А сейчас я собственно ответил на первый Ваш вопрос. Подробней про паттерн можно прочитать на http://www.hibernate.org/43.html

Автор: SuperFly 3.2.2008, 15:19
Аа, вот так то лучше, а то просто процитировали меня. Вот это уже интересней, спасибо за ответ!

Автор: Greg 3.2.2008, 15:43
Пожалуйста.
Цитата(SuperFly @  3.2.2008,  15:19 Найти цитируемый пост)
а то просто процитировали меня
 smile
На самом деле я привык использовать Ctrl+Enter для перевода курсора на новую строку и по-моему одно время здесь редактор именно так работал.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)