简单的Groovy \ Grails代码:
def start = {
source.save()
def result = getJson(hotelSite, eng + index, [:])
parse(JSONObject.fromObject( result.json.text() ))
render "OK"
}
def parse = {JSONObject json ->
def cities = json.get("filter").cities
println cities
def kievHotels = getJson(hotelSite, eng + root + '/searchhotelsbycity', ['city' : 'kiev'])
kievHotels = JSONObject.fromObject(kievHotels.json.text())
println kievHotels
kievHotels.rows.each { ht->
HotelText hotelText = new HotelText(lang : 'en', name : ht.l_name, description : ht.description, address : ht.address)
hotelText.save(/*flush:true*/)
println "hotel text saved"
Hotel hotel = new Hotel(lat : ht.lat, lon : ht.lon, source : source, sourceid : ht.id)
hotel.addToHotelTexts(hotelText)
//hotel.save(/*flush:true*/)
println "hotel saved"
ht.options.each {op->
new HotelFeatures(lang:'en', name : op, source : source, hotel : hotel).save()
}
println "options saved"
ht.photos.each {ph->
new HotelPhotos(hotel : hotel, photourl : ph, type : 'hotel').save()
}
println "photo saved"
hotel.save()
}
println "THE END"
return "THE END"
}
def getJson = {uri, path, query ->
Thread.sleep(10)
return withHttp(uri: uri) {
return get(path : path, query : query) { resp, json ->
return ['response' : resp, 'json' : json ]
}
}
}
所有必须完美但grails在“start”方法结束后抛出异常\闭包执行(程序打印“THE END”,呈现“OK”消息然后抛出异常):
org.springframework.dao.InvalidDataAccessApiUsageException :对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例: com.stanfy.sweethome.domains.Hotel ;嵌套异常是
org.hibernate.TransientObjectException :对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例: com.stanfy.sweethome.domains.Hotel 在java.lang.Thread.run(Thread.java:619)
引起: org.hibernate.TransientObjectException :对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例: com.stanfy.sweethome.domains.Hotel ......还有1个
答案 0 :(得分:3)
在你的集合映射中,你必须指定cascade=CascadeType.ALL
(我不知道它在groovy中究竟是多少)。
该异常意味着您有一个其元素未被持久化的集合。只有在设置了上述选项后,Hibernate才会自动保留它们。
P.S。有关此异常的数百个线程(在SO上也是如此),您可以搜索。
答案 1 :(得分:1)
您的HotelPhotos
对象上是否有HotelFeatures
和Hotel
的集合?如果是这样,您需要使用hotel.addToHotelPhotos(...)
和hotel.addToHotelFeatures(...)
添加每个内容,就像使用HotelTexts
一样。
然后你应该只需要在酒店调用一次保存,并保存所有其他实例(因为默认行为是级联)。