Grails:如何在异步Web请求后将对象保存到DB?

时间:2017-04-11 09:01:52

标签: multithreading grails jdbc gorm


我很难编程并行服务。目标是通过异步API调用从Facebook检索数据,然后同步迭代检索到的数据执行GORM操作。

异步获取数据的第一步似乎可以正常使用:

List<Activity> activityList = Activity.findAllByFacebookPageIsNotNullAndFetchEvents(true, [max: 100])
PromiseList promiseList = new PromiseList()
activityList.each { Activity activity->
    promiseList << { fetchEventData(activity.facebookPage, null) }
}

现在我试图迭代结果,例如:

promiseList.onComplete { List results ->
    results.each { ArrayList eventSet ->
        eventSet.each { LazyMap eventData ->
            createEvent(eventData)
        }
    }
}

createEvent()方法尝试保存新的Event。此操作失败,并显示:

2017-04-11 10:56:47.018错误--- [ctor Thread 129] o.h.engine.jdbc.spi.SqlExceptionHelper:语句关闭后不允许任何操作。 2017-04-11 10:56:47.024错误--- [ctor Thread 124] o.h.engine.jdbc.spi.SqlExceptionHelper:语句关闭后不允许任何操作。 2017-04-11 10:56:47.024错误--- [ctor Thread 125] o.h.engine.jdbc.spi.SqlExceptionHelper:无法转换价值&#39; 2017-01-11 23:31:39&#39;从第3列到TIMESTAMP。 2017-04-11 10:56:47.025错误--- [ctor Thread 105] o.h.engine.jdbc.spi.SqlExceptionHelper:语句关闭后不允许任何操作。 2017-04-11 10:56:47.026错误--- [ctor Thread 103] o.h.engine.jdbc.spi.SqlExceptionHelper:语句关闭后不允许任何操作。 2017-04-11 10:56:47.026错误--- [ctor Thread 107] o.h.engine.jdbc.spi.SqlExceptionHelper:语句关闭后不允许任何操作。

所以我想从各种线程调用createEvent()而不是&#34; main&#34;线。

有人可以告诉我如何以正确的方式做到这一点吗?

修改

我也尝试过:

List<ArrayList> promiseResult = promiseList.get()
promiseResult.each { ArrayList<LazyMap> eventList ->
    eventList.each {
        Event.findByFacebookId((String) it['id'])
        //createEvent(it)
    }
}

java.lang.NullPointerException

失败

2 个答案:

答案 0 :(得分:1)

试试这个

Event.withNewSession {
    Event.withNewTransaction {
        // Event update code here
    }
}

答案 1 :(得分:0)

感谢您的回答。我认为他们让我走上正轨。也许我不能清楚自己想要实现的目标。 GORM调用不是异步的,这是不必要的。虽然这似乎仍然是一个好主意!我的方法是减慢速度:D

然而,我使用waitAll()并在之后进行数据库处理后实现了所需的行为。

一个工作示例是:

List<Activity> activityList = Activity.findAllByFacebookPageIsNotNullAndFetchEvents(true, [max: 100])
List promises = []
activityList.each { Activity activity->
    promises << task { fetchEventData(activity.facebookPage, null) } // query website asynchronously; this is really fast!
}

def promisesResults = waitAll(promises)

promisesResults.each { ArrayList<LazyMap> eventList ->
    eventList.each { LazyMap eventData ->
        try {
           createEvent(eventData) // DB actions; this is pretty slow
        } catch (e) {
            log.error(e.toString())
        }
    }
}