ошибка grails PatchedDefaultFlushEventListener - PullRequest
1 голос
/ 02 января 2012

Я надеюсь, что кто-нибудь может помочь мне здесь. Я пытаюсь создать программу загрузки, которая может загружать один или несколько файлов mp3 и добавлять их атрибуты в базу данных (название песни, альбом и т. Д.). Я не уверен, является ли проблема, с которой я сталкиваюсь, из-за проблемы с базой данных или потому, что я действительно не понимаю, как работает CommonsMultipartFile. Во всяком случае, вот мой код "

Вид:

<g:form name="fileupload" url="[action:'uploads',controller:'fileResource']" method="POST" enctype="multipart/form-data">        
    <span>Add files...</span>
    <input type="file" name="files" multiple>           
</g:form>

fileResource:

def uploads = {                
    Collection result = []
    if (request instanceof MultipartHttpServletRequest) {
        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
        CommonsMultipartFile file = (CommonsMultipartFile)multiRequest.getFile("files");            
            println"one"
            moveFile(file)
            println"three"            
        result << [name: file.originalFilename, size:file.size]
    }        
    render result as JSON
}

private moveFile(CommonsMultipartFile file){
    println"two"
    try{            
        def userId = getUserId()
        def newFileName = java.util.UUID.randomUUID().toString()                    
        def userGuid = SecUser.get(userId.id).uid
        def webRootDir = servletContext.getRealPath("/")            
        File myFile = new File( webRootDir +  "/myUsers/${userGuid}/music",newFileName + ".")
        file.transferTo(myFile)
        MP3File mp3file = new MP3File(myFile);
        String    duration = mp3file.getAudioHeader().getTrackLength()
        String    bitRate = mp3file.getAudioHeader().getBitRate()
        String    encodingType = mp3file.getAudioHeader().getEncodingType()
        String    getFormat = mp3file.getAudioHeader().getFormat()
        String    trackLength = mp3file.getAudioHeader().getTrackLength()
        String    fileName = file.originalFilename
        String     artistName = ""
        String     albumName = ""
        String     songName = ""

        def getArtistId=""
        try{
            if (mp3file.hasID3v2Tag()){
                //println("has id3v2 tag")
                ID3v24Tag id3v24tag = mp3file.getID3v2TagAsv24();
                artistName = (id3v24tag.getFirst(ID3v24Frames.FRAME_ID_ARTIST).trim())
                albumName = (id3v24tag.getFirst(ID3v24Frames.FRAME_ID_ALBUM).trim())
                songName = (id3v24tag.getFirst(ID3v24Frames.FRAME_ID_TITLE).trim())
            }else if (mp3file.hasID3v1Tag()) {
                //println("has id3v1 tag")
                ID3v1Tag tag = mp3file.getID3v1Tag();
                artistName = tag.getFirst(FieldKey.ARTIST).trim()
                albumName = tag.getFirst(FieldKey.ALBUM).trim()
                songName = tag.getFirst(FieldKey.TITLE).trim()
            }
            else{
                println("this format not yet supported:" + getFormat)
            }
        }catch (Exception ex) {
            log.error("ERROR:  FILE NOT PROCESSED")
        }

        try{
            def oArtist = ""
            def c = Artist.createCriteria()
            def getMyArtist = c.get {
                eq('artistName', artistName )
                secUser {
                    eq('id', userId.id)
                }
            }
            if (getMyArtist == null){
                //artist does not exist
                //    1c.  add artist
                //    1d.  add album
                //    1e.  add song
                //    1f.  move song
                //    1g.  DONE
                oArtist=  new com.jason.score.Artist(
                    artistName : artistName    ,
                    secUser : userId.id
                )
                userId.addToArtist(oArtist).save(flush:true)
                def oAlbum     =  new Album
                (
                    albumName:        albumName
                )
                oArtist.addToAlbum(oAlbum).save(flush:true)

                def oSong = new Song
                (
                    fileLocation: webRootDir + "myUsers/${userGuid}/music/",
                    songBitRate: bitRate,
                    songDuration: duration,
                    songEncodeType: encodingType,
                    songName: songName
                )
                oAlbum.addToSong(oSong).save(flush:true)
            }else{
                //artist exists with that username
                //need album name and artist id
                def d = Album.createCriteria()
                def getMyAlbum = d.get {
                eq('albumName', albumName )
                artist {
                    eq('id', getMyArtist.id)
                }
                        }
                if(getMyAlbum == null){
                    //                3.  add album
                    //                3a.  add song
                    //                3b.  move song
                    //                3c.  DONE                                
                    Artist findArtist = Artist.get(getMyArtist.id)
                    def oAlbum     =  new Album
                    (
                        albumName:        albumName
                    )
                    findArtist.addToAlbum(oAlbum).save(flush:true)
                    def oSong = new Song
                    (
                        fileLocation: webRootDir + "myUsers/${userGuid}/music/",
                        songBitRate: bitRate,
                        songDuration: duration,
                        songEncodeType: encodingType,
                        songName: songName
                    )
                    oAlbum.addToSong(oSong).save(flush:true)
                    }else{
                        //album does exist
                        //check if song exists with album id                            
                        def e = Song.createCriteria()
                        def getMySong = e.get {
                            eq('songName', songName )
                            album {
                                eq('id', getMyAlbum.id)
                            }
                        }
                        if (getMySong==null){
                            Album findAlbum = Album.get(getMyAlbum.id)                                
                            def oSong = new Song
                            (
                                fileLocation: webRootDir + "myUsers/${userGuid}/music/",
                                songBitRate: bitRate,
                                songDuration: duration,
                                songEncodeType: encodingType,
                                songName: songName
                            )
                            findAlbum.addToSong(oSong).save(flush:true)
                        }else{
                            //it already exists, so do nothing
                        }                


                    }
                }                        
        }catch (Exception ex){
            log.error("ERROR: ADDING TO DB: " + ex)
        }
    }catch (Exception ex){
        log.error("error" + ex)
    }
}

    private getUserId(){
    return SecUser.get(springSecurityService.principal.id)
}
private getUser(){
    return SecUser.get(springSecurityService.principal)
}

Я получаю ошибку:

2012-01-02 14:25:25,314 [http-8080-1] ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.jason.score.SecUser#1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener.performExecutions(PatchedDefaultFlushEventListener.java:46)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.springframework.orm.hibernate3.HibernateTemplate$28.doInHibernate(HibernateTemplate.java:883)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:881)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod$1.doInHibernate(SavePersistentMethod.java:58)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod.performSave(SavePersistentMethod.java:53)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod.doInvokeInternal(AbstractSavePersistentMethod.java:179)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
....

2012-01-02 14: 25: 25,379 [http-8080-1] ERROR errors.GrailsExceptionResolver - Исключительная ситуация при обработке запроса: [POST] /com.jason.score/fileResource/uploads Stacktrace следует: org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: объект класса [com.jason.score.SecUser] с идентификатором [1]: оптимистическая блокировка не удалась; вложенное исключение - org.hibernate.StaleObjectStateException: строка была обновлена ​​или удалена другой транзакцией (или отображение несохраненного значения было неправильным): [com.jason.score.SecUser # 1] на java.lang.Thread.run (Thread.java:662) Вызвано: org.hibernate.StaleObjectStateException: строка была обновлена ​​или удалена другой транзакцией (или отображение несохраненного значения было неверным): [com.jason.score.SecUser # 1] ... еще 1

1 Ответ

1 голос
/ 03 января 2012

Ошибка связана с Hibernate.Вероятно, ошибка в ваших критериях запросов.Это выглядит как вероятный кандидат

oAlbum.addToSong(oSong).save(flush:true)

Это должны быть отдельные операции.Запросы критериев должны быть инкапсулированы методами на уровне сервиса.Для таких простых операций вы, вероятно, не увидите большой пользы от использования критериев по сравнению с динамическими искателями GORM.

Вы также пытаетесь сделать слишком много в одном месте.Рефакторинг вашего контроллера, чтобы использовать сервис для выполнения этих операций.Разбейте moveFile() на несколько методов для анализа MP3File, а затем передайте его другому методу, чтобы добавить его в песни пользователя.

Вам не нужно использовать идентификатор пользователя, если вы создаете связь непосредственно в домене.

Напишите несколько тестов для каждого атомарного элемента, и это должно облегчить поиск ошибки.

...