2010-01-21 4 views
4

je ce que je pense est un problème simple, mais ont été incapables de résoudre ... Pour une raison quelconque, j'ai un contrôleur qui utilise removeFrom * .save() qui renvoie pas d'erreur, mais ne fait rien.removeFrom * ne fonctionne pas et sans erreur

Exécution Grails 1.2 Linux/Ubuntu

L'application suivante est dépouillée de reproduire le problème ...

j'ai deux objets de domaine via create-domain-classe - emploi (qui a de nombreuses notes) - note (qui appartient à l'emploi)

J'ai 3 contrôleurs via créer contrôleur - JobController (échafaudage en cours d'exécution) - NoteController (SCAF en cours d'exécution fold) - JSONNoteController

JSONNoteController a une méthode primaire deleteItem qui vise à supprimer/supprimer une note.

Il effectue les opérations suivantes

  • une validation de la demande
  • supprime la note du travail - jobInstance.removeFromNotes (noteInstance) .save()
  • supprime la note - noteInstance.delete()
  • renvoie un état et un jeu de données restants sous la forme d'une réponse json.

Quand je lance cette demande - je reçois pas d'erreur, mais il semble que jobInstance.removeFromNotes (noteInstance) .save() ne fait rien et ne jette pas une exception, etc. Comment puis-je retrouver pourquoi ??

J'ai joint un exemple d'application qui ajoute des données via BootStrap.groovy. Il suffit de l'exécuter - vous pouvez afficher les données via les vues d'échafaudage par défaut.

Si vous utilisez Linux, à partir d'une ligne de commande, vous pouvez exécuter le suivant GET « http://localhost:8080/gespm/JSONNote/deleteItem?job.id=1&note.id=2 »

Vous pouvez exécuter encore et encore et rien d'autre qui se passe. Vous pouvez également coller l'URL dans votre navigateur Web si vous utilisez Windows.

S'il vous plaît aider - je suis coincé !!! code est ici link text

Remarque Domaine

package beachit 

class Note 
{ 

    Date dateCreated 
    Date lastUpdated 

    String note 

    static belongsTo = Job 

    static constraints = 
    { 
    } 

    String toString() 
    { 
     return note 
    } 
} 

emploi Domaine

package beachit 

class Job 
{ 

    Date dateCreated 
    Date lastUpdated 

    Date  createDate 
    Date  startDate 
    Date  completionDate 

    List notes 

    static hasMany = [notes : Note] 

    static constraints = 
    { 
    } 

    String toString() 
    { 
     return createDate.toString() + " " + startDate.toString(); 
    } 
} 

JSONNoteController

package beachit 

import grails.converters.* 
import java.text.* 

class JSONNoteController 
{ 

    def test = { render "foobar test" } 

    def index = { redirect(action:listAll,params:params) } 

    // the delete, save and update actions only accept POST requests 
    //static allowedMethods = [delete:'POST', save:'POST', update:'POST'] 

    def getListService = 
    { 
     def message 
     def status 
     def all = Note.list() 

     return all 
    } 

    def getListByJobService(jobId) 
    { 
     def message 
     def status 

     def jobInstance = Job.get(jobId) 
     def all 

     if(jobInstance) 
     { 
      all = jobInstance.notes 
     } 
     else 
     { 
      log.debug("getListByJobService job not found for jobId " + jobId) 
     } 

     return all 

    } 

    def listAll = 
    { 
     def message 
     def status 
     def listView 

     listView = getListService() 
     message  = "Done" 
     status  = 0 

     def response = ['message': message, 'status':status, 'list': listView] 
     render response as JSON 
    } 

    def deleteItem = 
    { 
     def jobInstance 
     def noteInstance 
     def message 
     def status 
     def jobId = 0 
     def noteId = 0 
     def instance 
     def listView 
     def response 

     try 
     { 
      jobId = Integer.parseInt(params.job?.id) 
     } 
     catch (NumberFormatException ex) 
     { 
      log.debug("deleteItem error in jobId " + params.job?.id) 
      log.debug(ex.getMessage()) 
     } 

     if (jobId && jobId > 0) 
     { 
      jobInstance = Job.get(jobId) 

      if(jobInstance) 
      { 
       if (jobInstance.notes) 
       { 
        try 
        { 
         noteId = Integer.parseInt(params.note?.id) 
        } 
        catch (NumberFormatException ex) 
        { 
         log.debug("deleteItem error in noteId " + params.note?.id) 
         log.debug(ex.getMessage()) 
        } 

        log.debug("note id =" + params.note.id) 
        if (noteId && noteId > 0) 
        { 
         noteInstance = Note.get(noteId) 
         if (noteInstance) 
         { 
          try 
          { 
           jobInstance.removeFromNotes(noteInstance).save() 
           noteInstance.delete() 

           message = "note ${noteId} deleted" 
           status = 0 
          } 
          catch(org.springframework.dao.DataIntegrityViolationException e) 
          { 
           message = "Note ${noteId} could not be deleted - references to it exist" 
           status = 1 
          } 
          /* 
          catch(Exception e) 
          { 
           message = "Some New Error!!!" 
           status = 10 
          } 
          */ 
         } 
         else 
         { 
          message = "Note not found with id ${noteId}" 
          status = 2 
         } 
        } 
        else 
        { 
         message = "Couldn't recognise Note id : ${params.note?.id}" 
         status = 3 
        } 
       } 
       else 
       { 
        message = "No Notes found for Job : ${jobId}" 
        status = 4 
       } 
      } 
      else 
      { 
       message = "Job not found with id ${jobId}" 
       status = 5 
      } 

      listView = getListByJobService(jobId) 

     } // if (jobId) 
     else 
     { 
      message = "Couldn't recognise Job id : ${params.job?.id}" 
      status = 6 
     } 

     response = ['message': message, 'status':status, 'list' : listView] 
     render response as JSON 

    } // deleteNote 
} 
+0

Vous ne savez pas si c'est utile, mais La modification des fonctions save() et delete to save (flush: true) et delete (flush: true) provoque l'exception suivante lors de l'appel delete(): org.springframework .dao.InvalidDataAccessApiUsageException: l'objet supprimé serait ré-enregistré en cascade (supprimer l'objet supprimé des associations) –

+0

J'ai aussi eu quelques problèmes avec removeFrom * dans Grails 1.1.1 que je n'ai jamais réussi à comprendre. – Kimble

+0

Intéressant ... le même code fonctionne dans BootStrap.groovy mais pas dans le contrôleur. S'il n'y a pas d'autres commentaires, je pourrais juste soulever un problème dans Jira .. Je ne vois rien de mal avec le code. – sub

Répondre

3

Voir ce fil: http://grails.1312388.n4.nabble.com/GORM-doesn-t-inject-hashCode-and-equals-td1370512.html

Je vous recommande d'utiliser une classe de base pour vos objets de domaine comme celui-ci:

abstract class BaseDomain { 

    @Override 
    boolean equals(o) { 
     if(this.is(o)) return true 
     if(o == null) return false 
     // hibernate creates dynamic subclasses, so 
     // checking o.class == class would fail most of the time 
     if(!o.getClass().isAssignableFrom(getClass()) && 
      !getClass().isAssignableFrom(o.getClass())) return false 

     if(ident() != null) { 
      ident() == o.ident() 
     } else { 
      false 
     } 
    } 

    @Override 
    int hashCode() { 
     ident()?.hashCode() ?: 0 
    } 

} 

De cette façon, les deux objets avec le même identifiant de base de données non NULL seront considéré comme égal.

+0

Je suis confus par ceci; pourquoi l'implémentation de equals/hashCode aurait-elle quelque chose à voir avec la possibilité de supprimer un objet d'une collection? –

+0

@CharlesWood GORM n'implémente pas equals et hashCode pour vous. Ainsi, deux instances du même objet (l'instance renvoyée par get (noteId) est une nouvelle instance) avec le même identifiant ne sont pas égales(), donc rien n'est supprimé de la collection. – noah

+0

noah, qu'est-ce que 'ident()' do/get? pourquoi pas '.id'? –

5

Je l'ai ... travailler si je ne peux pas expliquer pourquoi.

j'ai remplacé la ligne suivante dans deleteItem

noteInstance = Note.get(noteId) 

avec le

suivant
noteInstance = jobInstance.notes.find { it.id == noteId } 

Pour une raison quelconque le jobInstance.removeFromNotes travaille avec l'objet retourné par cette méthode au lieu de .get Ce qui fait il est étrange que toutes les autres fonctions de gorm (pas vraiment sur les fonctions dynamiques) fonctionnent avec la méthode noteInstance.get (noteId).

Au moins ça marche bien !!

+2

Il semble que les grails lui-même suggèrent de supprimer des éléments d'une collection de domaines. Voir: http://grails.org/doc/latest/ref/Domain%20Classes/removeFrom.html – lucke84

3

Je viens d'avoir ce même problème. La fonction removeFrom a réussi, la sauvegarde a réussi mais l'enregistrement physique dans la base de données n'a pas été supprimé. Voilà ce qui a fonctionné pour moi:

class BasicProfile { 
     static hasMany = [ 
       post:Post 
     ] 
    } 

    class Post { 
     static belongsTo = [basicProfile:BasicProfile] 
    } 

    class BasicProfileController { 
     ... 

def someFunction 
    ... 
     BasicProfile profile = BasicProfile.findByUser(user) 

      Post post = profile.post?.find{it.postType == command.postType && it.postStatus == command.postStatus} 

     if (post) { 
      profile.removeFromPost(post) 
      post.delete() 
     } 
     profile.save() 

    } 

Il est la combinaison du removeFrom, suivie d'une suppression sur le domaine associé, puis une sauvegarde sur l'objet de domaine.

+0

J'ai également trouvé que l'appel delete() était nécessaire, mais je ne sais pas pourquoi. –

+0

Oui, sans 'delete()' ça ne marche pas non plus pour moi dans Grails 3. J'ai supposé que 'removeFrom()' était suffisant pour effacer. – Guus