2010-12-31 8 views
0

私はサービスを持っており、ドメインオブジェクトを作成してそれを保存しようとしています。
それはセーブ一部になったとき、私はサービスの内部のドメインオブジェクトを保存するために何をする必要がありますどのようなエラーGrails - ドメインオブジェクトをサービス内に保存するには?

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

を取得します。インターネット上のすべてが、これは単に動作するはずのように見えます....

編集:
詳細: 私はこの記事全体で同様のシナリオである
Hibernate session in 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がhistoricalDataを何度も呼び出しています。上記のコードでは、それが最初のレコードを保存しているが、その後、第二の記録に私はエラーを取得しています:

Could not open Hibernate Session; nested exception is org.hibernate.SessionException: Session is closed!

編集:
ので、この上に読んでより多くの私が何であるかを理解すると思いますハプニング。
通常、コントローラから呼び出されると、休止状態のセッションがサービスに注入されます。
historyDataはコントローラ経由ではなくサードパーティのアプリケーションから呼び出されているため、セッションが閉じられていると告げるので、休止状態のセッションはサービスに注入されません。

サービスがコントローラから呼び出されていない場合、Grailsドメインモデルオブジェクト(つまりHistoricalContractData)を保存するために、新しいハイバーネーションセッションを作成するにはどうすればよいのでしょうか?
上記のように、NewSessionは機能していません。私はそういう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オブジェクトを保存するために、セッションオブジェクトを使用する方法を理解していません。

答えて

0

サービスのトランザクションコンテキストを指定する必要があります。 Grailsのサービスが完了したことを確認してくださいthis way

別のGrailsサービスへのリンク:

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

+0

あなたはサービス範囲を意味していますか?私のサービスはシングルトンです。いくつかの例や文書を私に教えてもらえますか?ありがとう –

+0

あなたは "このように"私は元々は私のサービスを作成するためにチュートリアルに従ったが、ドキュメントはこのトピックではまばらなように意味するものについてより具体的にするのに役立ちますか? –

+0

あなたのコードをすべて見ることなく、より具体的にすることはできません。率直に言って、私は時間を費やしたいとは思っていません。私は今夜​​出かける! – duffymo

4

サービスメソッドは、トランザクションも、デフォルトでは、セッションを持っている必要があります。そうでない場合、おそらくGrailsの規約に従わないことになります:

  1. サービスはgrails-appのサービスディレクトリにありますか?
  2. サービス名/ファイルの末尾が「サービス」ですか?
  3. サービスまたはサービスメソッド自体をトランザクションとは何とかしないでください。
  4. コントローラからサービスを呼び出していませんか?
  5. 依存関係注入を使用して、サービスをどこからでも使用できるようにしていますか?あなたはいつもあなたが持っているコードは「矢」を持っていない

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

    または

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

    で新しいセッションを作成を行うことによって、トランザクションを作成することができ、言っ

閉鎖に必要である。

EDIT、あなたの更新のために、あなたはセッションを使用する方法について

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

をチェックアウトする必要があります。基本的に、あなたはまた、単に

session.save(hcd) 

を行うことができる必要があり、あなた)あなたがsessionFactory.getCurrentSession(呼び出し後のGrails で、通常のように)(hcd.saveを行うことができるかもしれない - 理由私はこれが動作するかもしれないと思う方法は、新しいセッションを作成し、threadlocal経由で現在のスレッドにバインドする必要があります。

+0

@hvtgotcodesありがとうございます。私はそれらの慣習の大部分を守っていると思います。サービス内のhistoricalData関数がサードパーティのAPI(別のアプリ)によって呼び出されているため、#4はありません。 –

+0

@ w-他のアプリはあなたのサービスをどのようにしていますか? Webリクエスト(REST APIなど)で呼び出す場合は、サービスの前にコントローラが必要です。私が示したように矢印を追加しても問題ありません。 – hvgotcodes

+0

@hvgotcodes上記のように、サービスはサードパーティのAPIによって提供されるインターフェイスであるEWrapperを実装しています。 「HistoricalData」は、他のアプリがデータを与えるのに使うコールバック関数として登録されています。そのため、サービスはコントローラからのHTTP要求によって呼び出されません。それはちょうど...直接呼び出されています。これが明確になるのに役立ちますか? –

関連する問題