Details

    • Type: Sub-task Sub-task
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0
    • Fix Version/s: 1.1-beta1
    • Component/s: Controllers
    • Labels:
      None

      Description

      Currently the symantics of Hibernate are such that changes to the db are automatically performed and committed if an loaded Object is modified. So the User Object changes to the Database are performed when groovy execute "u.properties = params". So the Object is modified, but u.save() was never called.

      Seems that the loaded Object is bound to the Hibernate Session, so Hibernate checks the Object for changes.

      Unable to find source-code formatter for language: groovy. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
      def u = User.get(1)
      u.properties = params
      // validation fails here
      
      // Everything below is senseless for the "u" Object, because Changes are already written to the Database
      if(u.save()) {
      
      }
      else {
        // handle errors
      }
      

      I think this is very critical, because the Grails validation won't work correct.
      So a validation Error is displayed, but the Object has been modified ?!

      Is there a method to evict the Object from the Hibernate Session? (u.evict() doesn't work).

        Activity

        Hide
        Marc Palmer added a comment -

        Not sure if this is related but with 1.0.2 scaffolding when we delete we are getting:

        Caused by: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: Stockist.type; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: Stockist.type
        at StockistController$_closure4.doCall(StockistController.groovy:27)
        at StockistController$_closure4.doCall(StockistController.groovy)

        The line of code is the stockist.delete()

            def delete = {
                def stockist = Stockist.get( params.id )
                if(stockist) {
                    stockist.delete()
                    flash.message = "Stockist ${params.id} deleted"
                    redirect(action:list)
                }
                else {
                    flash.message = "Stockist not found with id ${params.id}"
                    redirect(action:list)
                }
            }
        

        The object being deleted has a "type" property that is null in the db due to it being old data before the property existed, and the Stockist class now has this property with a default value assigned to it:

        class Stockist {
            String name
            String nameOrNumber
            String addressLine1
            String addressLine2
            String town
            String county
            String postCode
            String type = Schema.STOCKISTTYPE_PUB
            
            static mapping = {
                cache usage:"nonstrict-read-write"
            }
            static constraints = {
                name(size:1..60, blank: false, nullable: false)
                nameOrNumber(size:0..60, blank: true, nullable: true)
                addressLine1(size:1..60, blank: false, nullable: false)
                addressLine2(size:0..60, blank: true, nullable: true)
                town(size:1..60, blank: false, nullable: false)
                county(size:0..60, blank: true, nullable: true)
                postCode(size:1..10, blank: false, nullable: false)
                type(size:1..20, blank:false, nullable: false, inList:Schema.STOCKISTTYPES)
            }
        }
        

        So the issue here is that it seems to be trying to SAVE when we call delete() which surely should not be happening, and makes me think this is related?

        Show
        Marc Palmer added a comment - Not sure if this is related but with 1.0.2 scaffolding when we delete we are getting: Caused by: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: Stockist.type; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: Stockist.type at StockistController$_closure4.doCall(StockistController.groovy:27) at StockistController$_closure4.doCall(StockistController.groovy) The line of code is the stockist.delete() def delete = { def stockist = Stockist.get( params.id ) if (stockist) { stockist.delete() flash.message = "Stockist ${params.id} deleted" redirect(action:list) } else { flash.message = "Stockist not found with id ${params.id}" redirect(action:list) } } The object being deleted has a "type" property that is null in the db due to it being old data before the property existed, and the Stockist class now has this property with a default value assigned to it: class Stockist { String name String nameOrNumber String addressLine1 String addressLine2 String town String county String postCode String type = Schema.STOCKISTTYPE_PUB static mapping = { cache usage: "nonstrict-read-write" } static constraints = { name(size:1..60, blank: false , nullable: false ) nameOrNumber(size:0..60, blank: true , nullable: true ) addressLine1(size:1..60, blank: false , nullable: false ) addressLine2(size:0..60, blank: true , nullable: true ) town(size:1..60, blank: false , nullable: false ) county(size:0..60, blank: true , nullable: true ) postCode(size:1..10, blank: false , nullable: false ) type(size:1..20, blank: false , nullable: false , inList:Schema.STOCKISTTYPES) } } So the issue here is that it seems to be trying to SAVE when we call delete() which surely should not be happening, and makes me think this is related?
        Hide
        Peter Ledbrook added a comment -

        Hi Marc,

        The delete() method simply calls session.delete(), so I think this is down to Hibernate. Just found a hibernate bug report that looks relevant to the behaviour you're seeing.

        Show
        Peter Ledbrook added a comment - Hi Marc, The delete() method simply calls session.delete() , so I think this is down to Hibernate. Just found a hibernate bug report that looks relevant to the behaviour you're seeing.
        Hide
        Peter Ledbrook added a comment -

        I'm going to send a mail to the dev list about this issue, but I think we should move it to 1.1 since it will almost certainly require a fairly significant change. We may switch to using the readOnly property on Hibernate domain instances, but we need to think on exactly how things should behave.

        Show
        Peter Ledbrook added a comment - I'm going to send a mail to the dev list about this issue, but I think we should move it to 1.1 since it will almost certainly require a fairly significant change. We may switch to using the readOnly property on Hibernate domain instances, but we need to think on exactly how things should behave.
        Hide
        Graeme Rocher added a comment -

        Grails not sets the object to read-only if a validation error occurs or a data binding error occurs, eliminating the lazy load problems that result from using discard()

        Show
        Graeme Rocher added a comment - Grails not sets the object to read-only if a validation error occurs or a data binding error occurs, eliminating the lazy load problems that result from using discard()
        Hide
        Caine added a comment -

        This is excellent news. Thank you very much for this.

        Show
        Caine added a comment - This is excellent news. Thank you very much for this.

          People

          • Assignee:
            Graeme Rocher
            Reporter:
            Martin Kremers
          • Votes:
            10 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development