Zaryab baloch
Zaryab baloch

Reputation: 119

Grails 3 : SessionFactory Bean is not injecting in Service

I am trying to bulk add data from a file, i read a method from this portal to bulk add the data using batch processing

http://krixisolutions.com/bulk-insert-grails-gorm/

When i used this technique and changed my app according to it my code is not working, i've been working for days to find method to bulk save the data to make the process faster, by simple manual flush it takes 4 minutes to save 1000 lines of data in database, i want to make this time as little as possible

In the below given code whenever i debug the code it does stop after SessionFactory, i dont understand what the problem is, as i am very new to grails and dont have any experience with sessionFactory or transactions.

Here is my code:

   runAsync {
            res = benchmark { result ->
                    Session session = SessionFactory.openSession()
Transaction tx = (Transaction)session.beginTransaction()




                    groovyFile.eachLine {


                        String[] tagData = it.split(',')

                        def isTimeToLive = true


                        if (isTimeToLive) {
                            try {
                                caller = new Caller(callingNumber: 
                       tagData.getAt(0), callerName: tagData.getAt(1))
                                session.save(caller)
                            } catch (Exception ex) {
                                log.error(ex.getMessage())
                            }

                            caller.validate()
                            if (caller.hasErrors()) {
                                println("message", "Invalid calling number. Digits can only be from 10 to 15.")
                            }

                            callCallerList = new CallCallerList(caller: caller, callerList: callerList)
                            callCallerList.validate()
                            if (callCallerList.hasErrors()) {
                                println("message", "Invalid calling number. Digits can only be from 10 to 15.")
                            } else {
                                session.save(callCallerList)
                            }

                        }
                        count++;
                        if (count % 100 == 0) {
                            session?.flush()
                            session?.clear()
                        }
                    }
                    tx.commit();
                    session.close();

                }


            }

        }

Upvotes: 1

Views: 648

Answers (2)

injecteer
injecteer

Reputation: 20707

In Grails you can simply use withSession{} or withTransaction{}:

I would write like that:

Caller.withTransaction{
  int count = 0
  groovyFile.splitEachLine( ',' ){ String[] line ->
    Caller caller = new Caller( callingNumber:line[ 0 ], callerName:line[ 1 ] )
    if( !caller.save( flush:0 == count % 100 ) ) println caller.errors
    count++
  }
}

You should not really handle the session by hand.

UPDATE

Why transaction do a rapid insertion while sessions fail?

No. Usually, a transaction wraps a session automatically, so withSession{} works as fast as withTransaction{}.

Is it because session was not cleaning the cache properly or because each sql query was doing its own flush?

Yes, session's cache is not cleaned-up unless you flush it or close it. This is what is done in my code or in any recommendation about bulk processing in GORM or Hibernate.

Upvotes: 1

Trebla
Trebla

Reputation: 1174

openSession is not a static method, you should be injecting sessionFactory and opening a session if you don't already have one.

class SomeService {
  def sessionFactory
  void someMethod() {
    def session = sessionFactory.openSession() //or sessionFactory.currentSession, not sure how this works with async operations
    //all your stuff
    if(<threshold>) { 
       session.flush()
       session.clear() //helps performance on exceptionally large imports, probably not so much on ~1000 records
    }
  }
}

Upvotes: 0

Related Questions