保存到MySql数据库时发生异常

保存到MySql数据库时发生异常,mysql,hibernate,grails,gorm,Mysql,Hibernate,Grails,Gorm,我在保存时遇到了一个奇怪的非确定性(看起来是这样)异常 控制器中的保存功能: for (cat in categories) { def recipeArray = recipeSource.getRecipes(cat) for(recipeString in recipeArray) { Recipe recipe def file = new File('recipes/'+recipeString+'.recip

我在保存时遇到了一个奇怪的非确定性(看起来是这样)异常

控制器中的保存功能:

for (cat in categories) {
    def recipeArray = recipeSource.getRecipes(cat)
        for(recipeString in recipeArray) {

            Recipe recipe

            def file = new File('recipes/'+recipeString+'.recipe')

            log.debug(recipeString+ ': Looking for recipe in DB')
            recipe = recipeService.findByName(recipeString)
            //recipe already in DB
            if(recipe){
                //add category to recipe
                log.debug('Recipe found. Adding category')
                recipeService.addCategory(recipe.id, cat)
            }
            else{
                log.debug(recipeString+ ': not found in DB')
                log.debug('Reading from disk...')

                try{

                        file.withObjectInputStream(getClass().classLoader){ois ->
                        recipe = ois.readObject()
                        println()
                    }
                }
                catch(Exception e){
                    log.error('Error while reading recipe from disk: '+recipeString)
                    log.error(e)

                }

                if(!recipe){
                    log.debug('downloading...')
                    recipe = recipeSource.getRecipe(recipeString)
                    if(!recipe){
                        log.error('Recipe is null!')
                        skipped++
                        writeToDisk(file, recipe)
                        continue
                    }
                }
                else{
                    // file found but not in DB -> broken recipe
                    continue
                }



                for(Tag tag in Tags){
                    recipeService.addTag(recipe, tag)
                }

                //invalid data
                if(!validateRecipe(recipe)){
                    log.error('Recipe invalid: '+recipe.getName())
                    skipped++
                    writeToDisk(file, recipe)
                    continue
                }

                //EXCEPTION OCCURS IN THE LINE BELOW
                recipeService.addCategoryToRecipe(recipe, cat)

                writeToDisk(file, recipe)

                try{
                    log.debug('saving recipe...')
                    def catName = cat.getName()
                    recipeService.addTag(recipe, catName)
                    recipeService.saveRecipe(recipe)
                    log.debug('Recipe saved: '+recipe.getName())
                    total++
                }
                catch(Exception e){
                    file.delete()
                    log.error('Error while savig recipe. Skipping..')
                    skipped++
                }
            }
        }
}
储蓄服务:

@Transactional
class RecipeService {

    DataSource dataSource
    TagService tagService

    @Transactional(readOnly = true)
    def getRecipe(id){
        Recipe.get(id)
    }

    def saveRecipe(Recipe recipe){
        recipe.save(flush: true, failOnError: true)
    }

    @Transactional(readOnly = true)
    def findByName(String name){
        Recipe.findByName(name)
    }

    def addCategoryToRecipe(Recipe recipe, de.mysexybody.Category cat){
        recipe.addToCategories(cat)
    }

    def addCategory(Long recipeId, Long categoryId){
        def category = Category.get(categoryId)
        def recipe = Recipe.get(recipeId)
        recipe.addToCategories(category)
        recipe.save(flush:true, failOnError:true)
    }

    def addTag(Recipe recipe, String tagString){
        for(Tag t in recipe.getTags()){
            if(t.getName() == tagString){
                return
            }
        }
        def savedTag = tagService.findTagByName(tagString)
        if(!savedTag){
            savedTag = tagService.saveTag(tagString)
            if(!savedTag){
                log.error(savedTag.errors)
                throw new Exception("Tag error")
            }
        }
        recipe.addToTags(savedTag)
    }
}
这里有一个例外:

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [10]; actual row count: 0; expected: 1
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at de.msb.RecipeController$$EOTUayCy.importRecipes(SportController.groovy:133)
    at de.msb.RecipeController$$EOTUayCy.index(SportController.groovy:20)
    at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
    at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
    at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:151)
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:282)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:203)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:181)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
2014-01-20 15:01:34 [ERROR] PatchedDefaultFlushEventListener: Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [10]; actual row count: 0; expected: 1
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at de.msb.RecipeController$$EOTUayCy.importRecipes(SportController.groovy:133)
    at de.msb.RecipeController$$EOTUayCy.index(SportController.groovy:20)
    at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
    at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
    at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:151)
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:282)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:203)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:181)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
现在是奇怪的部分。如果在发生此异常后重新启动应用程序(或仅启动保存功能),则以前未保存的对象现在不会出现问题。 每次重新启动时,应用程序可能会保存一个或多个对象,并再次抛出相同的异常

特别是,它是一个MySQLIntegrityConstraintViolationException,但不管出于什么原因,grails都没有显示它。我知道异常告诉了我什么,但我认为这只是一个其他错误的副作用,它似乎被应用程序或框架吞没了。我还试图将调试级别设置为“跟踪”,但没有发现任何有用的东西

到目前为止,我所尝试的:

  • 彻底验证所有域对象。我检查了可以保存的对象和导致异常的对象。它们都是有效的
  • 已检查应用程序的内存使用情况
  • 检查数据库进程

提前感谢您的帮助。

唯一可疑的是您将配方设置为
recipe=ois.readObject()
。在添加类别之前,请尝试保存它。整个文件处理仅用于备份目的。如果我想重新运行导入,我不需要再次下载所有内容。但我会删除它,然后再试一次。可能是因为您的服务是事务性的。您可以将单独调用返回的对象馈送到服务,这些对象位于不同的会话中。例如,尝试更改addCategoryToRecipe,以便只传递id。然后在该方法中再次检索对象,以确保对象处于同一会话中。希望我的解释不会令人困惑。我已经找到了解决问题的办法。我删除了
addCategoryToRecipe
,现在一切正常。尽管我不得不在另一个时间迭代并添加类别。虽然我现在可以完成我的任务,但我仍然想知道问题的原因是什么。