Grails - как сохранить доменный объект внутри Сервиса? - PullRequest
0 голосов
/ 01 января 2011

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

Сеанс Hibernate не связан с потоком, и конфигурация не позволяет создавать нетранзакционный сеанс здесь

Что мне нужно сделать, чтобы сохранить объект домена внутри службы.все в интернете делает так, что это должно работать просто ...

Редактировать:
дополнительные детали: я наткнулся на этот пост
Сессия Hibernate вthreads

, что аналогично сценарию.Мой сервис вызывается сторонним API.

Редактировать:
Я не очень хорошо объясняю это.Вот более полный код

import org.springframework.beans.factory.InitializingBean
import com.ib.client.EWrapper;


class BrokerService implements InitializingBean, EWrapper{

    static transactional = true

    private EClientSocket m_client
    private boolean m_disconnectInProgress = false

    void afterPropertiesSet(){
       // this.setting = grailsApplication1.config.setting
       m_client = new EClientSocket(this)
       m_disconnectInProgress = false

       connect()
    }


    def boolean connect() {
        m_client.eConnect()
        if (m_client.isConnected())
            return true

        return false
 }

    def void historicalData(int reqId, String date, double open,
   double high, double low, double close, int volume, int count,
   double WAP, boolean hasGaps)
    {   
        HistoricalContractData.withNewSession{session->
            println ' just before object create'
            def hcd = new sbi.investments.HistoricalContractData()
            hcd.hc_id = reqId
            hcd.data_date = new Date().parse('yyyyMMdd', date.replace('finished-', ''))
            hcd.open = open
            hcd.high = high
            hcd.low = low
            hcd.close = close
            hcd.volume =volume
            hcd.trade_count =count
            hcd.wap = WAP
            hcd.has_gaps = hasGaps.toString()
            println ' just before save'
            hcd.save()

            if(hcd.hasErrors()){
                println '=========== ERROR! ============'
                println hcd.errors
            }
        }
 }
}

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

Не удалось открыть сеанс Hibernate;вложенное исключение - org.hibernate.SessionException: сессия закрыта!

Редактировать:
поэтому, читая эту статью, я думаю, я понимаю, что происходит.
сеанс гибернации обычно внедряется в службу при вызове из контроллера.
Поскольку исторические данные вызываются из стороннего приложения, а не через контроллер, сеанс гибернации не вводится в службу, поэтому он жалуется, что сеансзакрыто.

Таким образом, я думаю, что реальный вопрос может быть, если служба не вызывается из контроллера, как мне создать новый сеанс гибернации для сохранения объекта модели домена grails (т.е. HistoricalContractData).
Как видно выше, withNewSession не работает.Должен ли я использовать SessionFactory, как это?
(не могу опубликовать ссылку на источник, потому что переполнение стека не нравится)

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class YourService  {

    SessionFactory sessionFactory // set by Dependency Injection

    public void yourMethod() {
        Session session = sessionFactory.getCurrentSession();
        // do something with session
    }
}

Я пытался это сделать, но не понимаю, какиспользуйте объект сеанса для сохранения объекта HistoricalContractData.

Ответы [ 2 ]

4 голосов
/ 01 января 2011

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

  1. Ваш сервис находится в каталоге сервисов grails-app?
  2. Ваше имя / файл службы оканчивается на «Служба»?
  3. Вы как-то сделали сервис или метод сервиса не транзакционным?
  4. Вы не вызываете сервис из контроллера?
  5. Используете ли вы внедрение зависимостей, чтобы получить доступ к вашим услугам везде, где бы вы их не использовали?

Тем не менее, вы всегда можете создать транзакцию, выполнив

AnyDomainObject.withTransaction{txStatus->
// do stuff like save here
}

или создайте новый сеанс с

AnyDomainObject.withNewSession{session->
// do stuff here
}

в вашем коде отсутствует «стрелка», необходимая для замыканий.

РЕДАКТИРОВАТЬ, для вас обновления, вы должны оформить заказ

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

о том, как использовать сеанс. По сути, вы должны быть в состоянии сделать только

session.save(hcd)

Кроме того, вы могли бы быть в состоянии сделать hcd.save () как обычно в grails после вы вызываете sessionFactory.getCurrentSession () - причина, по которой я думаю, что это может работать заключается в том, что метод должен создать новый сеанс и связать его с текущим потоком через threadlocal.

0 голосов
/ 01 января 2011

Вам необходимо указать контекст транзакции для вашего сервиса. Убедитесь, что ваши услуги Grails сделаны таким образом .

Другая сервисная ссылка Grails:

http://www.grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html

...