Search code examples
hibernategrailsgrails-orm

Grails Domain Object inside Command Object always saves


I have a Command Object that looks as follows...

@Validateable
class ACommand implements Serializable
{
  ADomainObject bundleDef
}

I use a form to fill the Command then use a controller similar to this

def save(ACommand command)

I also added the following to my Config.groovy

grails.gorm.autoFlush = false

The problem is even when I don't flush (or even call .save()) it still save to the DB upon return. Has anyone experienced this? Is there a way around it?

Update

Also tried the following

def save(ACommand command)
{
    try{
       service.saveADomainObject(command.adomain) //save called in here if no error
    }   
    catch(Exception e3){
        log.error(e3);
        command.adomain.discard()
    }
    // renders ...
}

This also does not work, even though the discard is called (I set a breakpoint) it still saves.

Update 2

I changed my service to look as follows

 adomain.discard()
 throw new InvalidObjectException("Blah Blah Blah")

It seems to save to the DB directly after the error is thrown. I also confirmed my service is transactional.

Update 3

Adding my service classes for reference

@Transactional(readOnly = true)
def saveADomainObject(def adomain, def test) throws InvalidParameterException, InvalidObjectException, Exception{
    if (!test)
    {
        throw new InvalidParameterException("*")
    }
    else
    {
        if (adomain?.id)
        {
            if (!isValidBundleName(adomain, test))
            {
                //TODO: Make default.cannot.save.message
                throw new InvalidObjectException("*")
            }
            errors = updateDomain(adomain)
        }
        else
        {
            errors = createNewdomain(adomain)
        }

        if (errors)
        {
            throw new Exception(errors)
        }
    }
}
protected def updateDomain(def adomain)
{
    adomain.updatedBy = user
    String errors=null;
    if (adomain.getErrors().allErrors.size() > 0)
    {
        errors = adomain.getErrors().allErrors.join("\n")
    }
    return errors
}
private def createNewdomain(def adomain)
{
    adomain.createdBy = user
    String errors = null
    if (adomain.getErrors().allErrors.size() > 0)
    {
        errors = adomain.getErrors().allErrors.join("\n")
    }
    return errors
}

Solution

  • This is how I managed to get it working...

    First in the service I added the @Transactional(readOnly = true) annotations based on this qoute

    This version defaults to all methods being read-write transactional (due to the class-level annotation), but the listBooks method overrides this to use a read-only transaction:

    That helped but now it wouldn't save period. So I tooke the .save() call out making my controller look like this...

    def save(ACommand command)
    {
      try{
       service.saveADomainObject(command.adomain) //save called in here if no error
       command.adomain(flush:true)
      }   
      catch(Exception e3){
        log.error(e3);
      }
      // renders ...
    }
    

    I needed the flush:true despite readding the autoFlush so I am not sure there.