Gr3go
Gr3go

Reputation: 724

GORM domain.delete(flush: true) not firing HibernateException nor other feedback?

Given:

Foo () {
  Bar bar

  static contraints = {
      bar (nullable: false)
  }
}

and a Service to manage Bar types, where a method deletes:

line 105: BarService {
line 106:     public BarCommand deleteBar(long Id) {    
line 107:         Bar b = Bar.get(Id)
line 108:         if (!b.delete(flush: true)) {
line 109:             //handle error here

If there is an existing Foo, "f" that already has a Bar of id 1 (for exmaple) associated with it, then line 108 should fail with some error explaining "b cannot be deleted, it is assigned to Foo id: 1" however, all that happens is line 108 returns false on truthiness and drops into the error handling regardless of whether delete was successful or not.

How do we know when we delete a domain whether the delete succeeded or failed? the doco does not describe this - Hibernate reports that a HibernateException should fire, but no exceptions are fired in any Unit test scenario...

(http://docs.grails.org/latest/ref/Domain%20Classes/delete.html)

I realize domain.delete() would not return anything as the delete is not communicated to the DB until a flush event, so I thought explicitly calling flush: true would address this, but it does not appear to.

Upvotes: 0

Views: 699

Answers (2)

sachin vinay
sachin vinay

Reputation: 1

I have used with transaction commit changes in database and its working great.

Read Object delete() in a controller no longer works without a Transaction as of 3.2.4 #10444 for more information.

def delete(long id) {

    Document FSDocumentInstance = Document.get(id)
    Document.withTransaction {
        if (FSDocumentInstance == null) {
            return
        }
        File file = new File(FSDocumentInstance.filePath)
        File test = new File(FSDocumentInstance.fullPath)
        test.delete()
        file.delete()
        FSDocumentInstance.delete()
        flash.message = "File deleted"
    }
        redirect(action: 'index')
    }
}

Upvotes: 0

Dónal
Dónal

Reputation: 187399

Personally I dislike the inefficiency of retrieving an object from the DB for the sole purpose of deleting it, so instead of this:

Bar b = Bar.get(Id)
if (!b.delete(flush: true)) {
  // handle error here
}

I would use HQL to perform the delete because this avoids the need to retrieve it first (the load() method is an alternative solution).

Integer rowsDeleted = Bar.executeUpdate('delete Bar where id = ?', [Id])
if (!rowsDeleted) {
  // handle error here
}

A further benefit of this approach is that executeUpdate returns the number of rows updated/deleted, so you can check whether the operation was successful.

Upvotes: 2

Related Questions