0

我正在尝试创建一个新的数据库对象,保存它,然后检查保存是否成功。这样做的正确方法是什么:

class Document {
    String externalId;

    static constraints {
        externalId(blank: false, unique: true);
    }        
}

def createDocuments(List<String> ids) {

    Document.withTransaction() {
        ids.each { String id ->
            new Document(externalId: id).save();
        }
    }

    // want to test here if transaction succeeded.
}

此事务可能会失败,因为其他用户可能同时创建了其中一个文档。因此,虽然一个实例是有效的(即它的 externalId 不为空),但它可能不是唯一的。但是不运行事务就无法判断。

该怎么办?

更新

根据到目前为止提供的答案,这是我的问题的症结所在:

如果我运行一个调用多个保存的事务,保存的对象何时可用于其他休眠会话?一些可能性:

  1. save通话返回时
  2. 事务提交时
  3. 其他一些不确定的时间(大概在#2之前)

如果save一个对象由于唯一性约束而失败,并且我回滚了事务,那么所有其他保存是否也会回滚,即使它们没有冲突?如果不是,那么将所有这些都包含在事务中的意义何在?

4

2 回答 2

0

您可以在实际保存到数据库之前验证对象。
您也可以使用异常处理,以防万一。
我在这类场景中遵循的一般模式是,

DomainClass.withTransaction{ tx ->
   try{
       def ref = new DomainClass(...)
       if(ref.validate()){
           ref.save()
       }
        else{
           //throw some invalid instance 

        }

    }
    catch(e){
      tx.setRollbackOnly()
      log.error e
    }
}
于 2013-06-19T07:46:03.447 回答
0

好的。在第 n 次阅读我最喜欢的文章后,这确实是有道理的。

externalId主键Document吗?如果是,那么这里使用的优化方法是existence在保存文档之前检查文档:

//Avoid duplication in the submission as well by using Set<String>
def createDocuments(Set<String> ids) { 
    Document.withTransaction {
        ids.each { String id ->
            //If `id` is not the primary key then use
            //if(!Document.findByExternalId(id)){}
            //This way you maintain the integrity of the Document.
            if(!Document.exists(id)){
                if(!new Document(externalId: id).save()){
                    //Validation failed on constraints. Handle them here
                }

                //You may not need to call save on each Document, 
                //unless you need to validate the constraints
                //as all of the Documents created will be automatically saved to 
                //cache and ultimately flushed to db by end of the session, which
                //is in this case exiting the action method.
            }
        }
    }

    // You do not need to test here if transaction succeeded.
}
于 2013-06-19T15:56:25.533 回答