我在保存时遇到了一个奇怪的非确定性(似乎是)异常。
控制器中的保存功能:
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都没有显示它。我知道异常告诉我什么,但我认为这只是其他错误的副作用,似乎被应用程序或框架吞噬了。我还尝试将调试级别设置为“跟踪”,但没有找到任何有用的信息。
到目前为止我尝试过:
提前感谢您的帮助。