Настройка сеанса EclipseLink - ошибка - PullRequest
1 голос
/ 25 марта 2011

В трехуровневом веб-проекте, использующем EclipseLink со всей бизнес-логикой в ​​БД, мне нужно выполнять хранимую процедуру до и после каждого отдельного хранимого вызова, будь то процедура или функция, в одном и том же сеансе.Это решение руководства, и я ничего не могу с этим поделать.Поэтому я перешел к настройке сеанса с помощью прослушивателей событий , но это не совсем работает.

Вот мой код в настройщике сеанса:, "log" - это log4j Logger.

SessionEventAdapter adapter = new SessionEventAdapter() {
    @Override
    public void preExecuteQuery(SessionEvent event) {
        log.debug("Setting environment parameters before query execution.");

        [some business code...]

        StoredProcedureCall call = wrapper.generateCall();

        DatabaseQuery query = new DataModifyQuery(call);

        event.getSession().executeQuery(query);

        preExecuteQuery(event);
    }

    @Override
    public void postExecuteQuery(SessionEvent event) {
        log.debug("Releasing environment parameters after query execution.");

        [some business code...]         

        StoredProcedureCall call = wrapper.generateCall();

        DatabaseQuery query = new DataModifyQuery(call);

        event.getSession().executeQuery(query);

        postExecuteQuery(event);
    }
};

session.getEventManager().addListener(adapter);

То, что я получаю, это то, что строка журнала "Установка параметров среды ..." повторяется не менее 600-800 раз, затем я получаю переполнение стекаошибка.Я понятия не имею, почему preExecuteQuery зацикливается бесконечно.Я что-то пропустил?Насколько я знаю, я делаю именно так, как кажется в вики EclipseLink.И прежде чем вы спросите, то же самое поведение с последней строкой или без нее preExecuteQuery(event);.

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

Есть идеи?Спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 28 марта 2011

Лучше всего проверить тип запроса и, если запрос является DataModifyQuery, не выполнять событие. Чтобы быть более точным в своем коде, вы можете добавить свойство в DataModifyQuery для проверки, чтобы не обрабатывались только запросы событий.

Также вы должны удалить вызовы "postExecuteQuery (event);" и "preExecuteQuery (event);" так как этот код будет повторно вызывать этот код события, что всегда приводит к переполнению стека.

0 голосов
/ 25 марта 2011

Полагаю, ваш звонок на executeQuery() снова вызывает preExecuteQuery() и postExecuteQuery(). Если это так, вы можете сделать что-то вроде этого:

SessionEventAdapter adapter = new SessionEventAdapter() {
    private ThreadLocal<Boolean> inListener = new ThreadLocal<Boolean>();

    @Override
    public void preExecuteQuery(SessionEvent event) {
        if (inListener.get() == Boolean.TRUE) return;
        inListener.set(true);
        try {
            ...
        } finally {
            inListener.remove();
        }
    }

    @Override
    public void postExecuteQuery(SessionEvent event) {
        if (inListener.get() == Boolean.TRUE) return;
        inListener.set(true);
        try {
            ...
        } finally {
            inListener.remove();
        }
    }
};
...