1
votes

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
}
2

2 Answers

1
votes

If ADomainObject bundleDef is bound to an object that is already persistent (i.e. if binding this object loads a record from the database), then changes to this object will automatically be saved to the DB when the Hibernate session is closed.

Assuming you don't want to save the object if the constraints are invalid do this:

def save(ACommand command) {

    if (!command.adomain.save()) {
        log.error "Failed to save domain due to errors $command.adomin.errors"
        // other error handling - maybe show a form that allows the user to correct the errors
    } else {
        // object saved successfully, redirect to homepage, throw a party, or whatever
    }
}
0
votes

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.