views:

373

answers:

2

Simple Groovy\Grails code:

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 ]

            }
        }
    }

All must be perfect but grails throws exception after the end of "start" method\closure execution(program prints "THE END", renders "OK" message and then throws exception):

org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.stanfy.sweethome.domains.Hotel; nested exception is

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.stanfy.sweethome.domains.Hotel at java.lang.Thread.run(Thread.java:619)

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.stanfy.sweethome.domains.Hotel ... 1 more

+1  A: 

In your collection mapping you have to specify cascade=CascadeType.ALL (I don't know how exactly it will be in groovy).

The exception means that you have a collection whose elements are not persisted. Hibernate persists them automatically only if the above option is set.

P.S. There are hundreds of threads (on SO as well) about this exception, you could've searched.

Bozho
+1  A: 

Do you have collections of HotelPhotos and HotelFeatures on your Hotel object? If so you will need to add each of them using hotel.addToHotelPhotos(...) and hotel.addToHotelFeatures(...), like you have with HotelTexts.

Then you should only need to call save on the hotel once and all the other instances will be saved (as the default behaviour is to cascade).

Dave