0

私はサービスを持っており、関数の 1 つの中でドメイン オブジェクトを作成して保存しようとしています。
保存部分に到達すると、エラーが発生します

スレッドにバインドされた Hibernate セッションはありません。構成では、ここで非トランザクション セッションを作成することはできません。

ドメイン オブジェクトをサービス内に保存するにはどうすればよいですか。インターネット上のすべてのものは、これがうまくいくように見えます....

編集:
追加の詳細:私はこの投稿に出くわしました
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 が historyData を数回呼び出しています。上記のコードでは、最初のレコードを保存していますが、2 番目のレコードでエラーが発生しています。

Hibernate セッションを開けませんでした。ネストされた例外は org.hibernate.SessionException: セッションが閉じられています!

編集:
これをもっと読んで、何が起こっているのか理解していると思います。
通常、休止状態のセッションは、コントローラーから呼び出されたときに Service に挿入されます。
historyData はコントローラー経由ではなく、サード パーティのアプリから呼び出されているため、休止状態のセッションがサービスに挿入されていないため、セッションが閉じていると不平を言っています。

したがって、本当の問題は、サービスがコントローラーから呼び出されない場合、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 オブジェクトを保存するためにセッション オブジェクトを使用する方法がわかりません。

4

2 に答える 2

4

サービスメソッドはトランザクション型であり、デフォルトでセッションが必要です。そうでない場合は、おそらくどういうわけかGrailsの規則に従っていません。

  1. あなたのサービスはgrails-appのservicesディレクトリにありますか?
  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)

また、 sessionFactory.getCurrentSession()を呼び出した後、通常のようにgrailsでhcd.save()を実行できる場合があります。これが機能すると思う理由は、メソッドが新しいセッションを作成し、それを現在のスレッドにバインドする必要があるためです。スレッドローカル経由。

于 2010-12-31T23:57:11.700 に答える
0

サービスのトランザクション コンテキストを指定する必要があります。Grails サービスがこの方法で行われていることを確認してください。

別の Grails サービス リンク:

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

于 2010-12-31T22:57:50.273 に答える