2015-05-23 33 views
1

我使用下面的代码 -Grails的保存(冲洗:真)不会立即坚持到数据库

Topic topic = new Topic() 
topic.name = "y u no save" 
topic.save(flush:true, failOnError:true) 

def promiseList = new PromiseList() 
subtopicNames.each { sName -> 
    promiseList << Topic.async.task { 
     Subtopic subtopic = new Subtopic() 
     subtopic.name = sName 
     /* ... long running tasks like web service call ... */ 
     log.info("Topic Id : $topic.id") 
     subtopic.topic = topic 
     subtopic.save(flush: true, failOnError: true) 
    } 
} 

def subtopics = promiseList.get() 

我得到这个错误 -

Detail: Key (topic_id)=(517333) is not present in table "topic".; nested exception is org.postgresql.util.PSQLException: ERROR: insert or update on table "subtopic" violates foreign key constraint "fkfd7d3e7098cf2d58" 
    Detail: Key (topic_id)=(517333) is not present in table "topic". 

当我检查数据库话题ID 517333,它实际上不存在,而在aync.task块中的日志打印“主题Id:517333”。这里发生了什么,如何在需要时强制保存主题。

Topic - 

class Topic { 
    String name 
    static hasMany = [subtopics: Subtopic] 
} 

Subtopic - 

class Subtopic { 
    String name 
    static belongsTo = [topic: Topic] 
} 
+0

请问你为什么试图异步添加你的子主题?如果您正在执行昂贵且长时间运行的进程,则异步可能会很有用,但我不确定这会有助于获得任何性能,而无需进行其他处理即可获得简单数据库插入的性能......此外,您将此代码放在哪里?它是否处于默认事务处理的服务方法中? – Philippe

+0

上面的代码是精简版本。实际上有很长时间的运行任务发生,比如在子主题创建中调用Web服务等。 是代码在默认事务处于服务中。 – vishesh

+0

好的,你可以粘贴你的Topic和Subtopic域类吗? – Philippe

回答

0

将域实例添加到使用hasMany关系的集合中的方法是将子域添加到父类的集合。 试试这个:

def promiseList = new PromiseList() 
def topic = new Topic(name: 'main topic') 
topic.save(failOnError: true, flush: true) 
def subtopics = ['subtopic 1', 'subtopic 2'] 

subtopics.each { topicName -> 
    promiseList << Topic.async.task { 
     Subtopic subtopic = new Subtopic(name: topicName) 
     // adding to the topic will cascade saves of the subtopics by default. 
     topic.addToSubtopics(subtopic) 
     /* ... long running tasks like web service call ... */ 
     return subtopic 
    } 
} 

// wait for tasks to complete 
def subtopicList = promiseList.get() 

// Saving the topic will cascade saves of the child subtopics 
topic.save(failOnError: true, flush:true) 

如果你想还是做你的方式,你可以禁用子主题的主题属性的限制,允许空:

class Subtopic { 
    //... 
    static constraints = { 
     topic nullable: true 
    } 
} 

然后,你可以这样做:

Subtopic subtopic = new Subtopic(name : topicName) 
subtopic.save(flush:true) 

并且在承诺同步后:

​​
+0

我之前使用过类似的解决方案。问题在于,因为我使用的承诺具有不同的hibernate会话,所以我必须在调用保存主题之前将子主题实例合并回主线程的hibernate会话中。这对于s​​ubtopic类中的顶级属性是很好的,但是我的子主题也有关联的对象,它们没有通过merge方法合并 – vishesh

+0

然后我想你需要禁用subtopic的topic属性的约束来允许一个可为null的属性。在一分钟内查看我的代码编辑... – Philippe

相关问题