Reputation: 119
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
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
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