title: concurrent transaction in grails resulting in database stale state exception
body: <p>following is my code that is run on an api call.The below code is in a grails service which are transactional by default.But even after locking the row,I am getting this error : <code>Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)</code>.There is just one plan in database so for loop is run just once.but there are concurrent calls to api which are causing error.Please help me fix this</p>
  
  <pre><code>def updateAllPlans(def user,def percentComplete,def chapterId){
          def plans = Plan.findAllWhere(user:user)
          def chapter = Chapter.findById(chapterId)
          for(def plan:plans){
                  def foundChapters = plan.psubject.ptopics.psubtopics.pchapters.chapter.flatten().contains(chapter)
                  if(foundChapters){
                      plan.lock()
                      if(percentComplete=='0'){
                          plan.durationViewComplete = plan.durationViewComplete.plusMillis(chapter.duration.getMillisOfSecond())
                          plan.durationViewComplete = plan.durationViewComplete.plusSeconds(chapter.duration.getSecondOfMinute())
                          plan.durationViewComplete = plan.durationViewComplete.plusMinutes(chapter.duration.getMinuteOfHour())
                          plan.durationViewComplete = plan.durationViewComplete.plusHours(chapter.duration.getHourOfDay())
                      }else{
                          plan.durationComplete = plan.durationComplete.plusMillis(chapter.duration.getMillisOfSecond())
                          plan.durationComplete = plan.durationComplete.plusSeconds(chapter.duration.getSecondOfMinute())
                          plan.durationComplete = plan.durationComplete.plusMinutes(chapter.duration.getMinuteOfHour())
                          plan.durationComplete = plan.durationComplete.plusHours(chapter.duration.getHourOfDay())
                      }
  
                      plan.save(flush:true, failOnError:true)
                  }
          }
      }
  </code></pre>