Dependent property in domain class

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Dependent property in domain class

Kenneth Kousen
Hi all,

I have a domain class Course that looks like this:

class Course {
  String title
  Date startDate
  Date endDate

  // other properties, toString() method, constraints as usual...
}

I would like to add a "length" property to Course, which is dependent on the existing startDate and endDate properties.  Since it's dependent, I don't want to provide a setter method, nor do I plan to store it in the database.  I tried just adding a getter method

def getLength() {
  int days = 0
  for (date in startDate..endDate) {
    days++
  }
  return days
}

but when I start up Grails I get an exception because the length property has no setter method.

What's the appropriate way to implement a "read-only" property in a domain class?  Would some use of the "transient" keyword work?  Should I be avoiding the domain class altogether and build a separate "view" class, with the attendant DRY violations?

Any advice would be appreciated,

Ken Kousen
--
Kenneth A. Kousen
President
Kousen IT, Inc.

Email: [hidden email]
Site: http://www.kousenit.com
Blog: http://kousenit.wordpress.com
Reply | Threaded
Open this post in threaded view
|

Re: Dependent property in domain class

Robert Fletcher
static transients = ['length']

Should do the trick, I believe

On 18/12/2007, Kenneth Kousen <[hidden email]> wrote:

> Hi all,
>
> I have a domain class Course that looks like this:
>
> class Course {
>   String title
>   Date startDate
>   Date endDate
>
>   // other properties, toString() method, constraints as usual...
> }
>
> I would like to add a "length" property to Course, which is dependent on the
> existing startDate and endDate properties.  Since it's dependent, I don't
> want to provide a setter method, nor do I plan to store it in the database.
> I tried just adding a getter method
>
> def getLength() {
>   int days = 0
>   for (date in startDate..endDate) {
>     days++
>   }
>   return days
> }
>
> but when I start up Grails I get an exception because the length property
> has no setter method.
>
> What's the appropriate way to implement a "read-only" property in a domain
> class?  Would some use of the "transient" keyword work?  Should I be
> avoiding the domain class altogether and build a separate "view" class, with
> the attendant DRY violations?
>
> Any advice would be appreciated,
>
> Ken Kousen
> --
> Kenneth A. Kousen
> President
> Kousen IT, Inc.
>
> Email: [hidden email]
> Site: http://www.kousenit.com
> Blog: http://kousenit.wordpress.com

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Dependent property in domain class

Kenneth Kousen
Yes it did, thanks.  I was able to use that line along with only the getter method to establish the property.  I didn't need to put in a setter or make "length" an attribute, either.

I tried putting my new property in a <g:sortableColumn> tag in a gsp.  While it appeared to work, clicking on it wound up sorting by startDate instead.  Any idea what that's all about?

Ken

On 12/18/07, Robert Fletcher <[hidden email]> wrote:
static transients = ['length']

Should do the trick, I believe

On 18/12/2007, Kenneth Kousen <[hidden email]> wrote:

> Hi all,
>
> I have a domain class Course that looks like this:
>
> class Course {
>   String title
>   Date startDate
>   Date endDate
>
>   // other properties, toString() method, constraints as usual...
> }
>
> I would like to add a "length" property to Course, which is dependent on the
> existing startDate and endDate properties.  Since it's dependent, I don't
> want to provide a setter method, nor do I plan to store it in the database.
> I tried just adding a getter method
>
> def getLength() {
>   int days = 0
>   for (date in startDate..endDate) {
>     days++
>   }
>   return days
> }
>
> but when I start up Grails I get an exception because the length property

> has no setter method.
>
> What's the appropriate way to implement a "read-only" property in a domain
> class?  Would some use of the "transient" keyword work?  Should I be
> avoiding the domain class altogether and build a separate "view" class, with
> the attendant DRY violations?
>
> Any advice would be appreciated,
>
> Ken Kousen
> --
> Kenneth A. Kousen
> President
> Kousen IT, Inc.
>
> Email: [hidden email]
> Site: http://www.kousenit.com
> Blog: http://kousenit.wordpress.com

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email




--
Kenneth A. Kousen
President
Kousen IT, Inc.

Email: [hidden email]
Site: http://www.kousenit.com
Blog: http://kousenit.wordpress.com
Reply | Threaded
Open this post in threaded view
|

RE: Dependent property in domain class

Jay Goldman
i think g:sortableColumn sets the sort param which is used to generate the hql used to retrieve the data to display (along with the order, offset, and max values).
that is, these properties are passed to the domain class's list method which does a hibernate call
 
 So i don't know how it can sort on other than domain data columns.
 
I also don't know if you can sort on a property of a one-to-one relationship (E.g., a Car has an Owner and you display and want to sort on the names of Owners).
 
Maybe there is a way to add computed column(s) to the underlying hql so they can participate in the selection and ordering of display data. Otherwise it seems to me that you would have to fetch all the data and sort it 'locally' instead of in the database.
 
Hopefully I am wrong and someone will correct me
 
jay


From: Kenneth Kousen [mailto:[hidden email]]
Sent: Tuesday, December 18, 2007 11:05 AM
To: [hidden email]
Subject: Re: [grails-user] Dependent property in domain class

Yes it did, thanks.  I was able to use that line along with only the getter method to establish the property.  I didn't need to put in a setter or make "length" an attribute, either.

I tried putting my new property in a <g:sortableColumn> tag in a gsp.  While it appeared to work, clicking on it wound up sorting by startDate instead.  Any idea what that's all about?

Ken

On 12/18/07, Robert Fletcher <[hidden email]> wrote:
static transients = ['length']

Should do the trick, I believe

On 18/12/2007, Kenneth Kousen <[hidden email]> wrote:

> Hi all,
>
> I have a domain class Course that looks like this:
>
> class Course {
>   String title
>   Date startDate
>   Date endDate
>
>   // other properties, toString() method, constraints as usual...
> }
>
> I would like to add a "length" property to Course, which is dependent on the
> existing startDate and endDate properties.  Since it's dependent, I don't
> want to provide a setter method, nor do I plan to store it in the database.
> I tried just adding a getter method
>
> def getLength() {
>   int days = 0
>   for (date in startDate..endDate) {
>     days++
>   }
>   return days
> }
>
> but when I start up Grails I get an exception because the length property
> has no setter method.
>
> What's the appropriate way to implement a "read-only" property in a domain
> class?  Would some use of the "transient" keyword work?  Should I be
> avoiding the domain class altogether and build a separate "view" class, with
> the attendant DRY violations?
>
> Any advice would be appreciated,
>
> Ken Kousen
> --
> Kenneth A. Kousen
> President
> Kousen IT, Inc.
>
> Email: [hidden email]
> Site: http://www.kousenit.com
> Blog: http://kousenit.wordpress.com

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email




--
Kenneth A. Kousen
President
Kousen IT, Inc.

Email: [hidden email]
Site: http://www.kousenit.com
Blog: http://kousenit.wordpress.com
Reply | Threaded
Open this post in threaded view
|

Re: Dependent property in domain class

jens.riboe
 >>So i don't know how it can sort on other than domain data columns
I had this problem too and solved it by changing the list controller
closure to check for params.sort and then for each non-domain property.
Similar to

def   list = {
    def lst
    switch (params.sort) {
        default:
           lst = Foobar.list(params)
           break
        case 'dependentProperty':
           def sort = params.remove('sort')
           lst = Foobar.list(params).sort { a,b ->
                if (params.order == 'desc') {def t=a; a=b; b=t;}
                return a.dependentProperty <=> b.dependentProperty
            }
           params.sort = sort
           break
    }
    [ foobarList: lst ]
}

I know this is a rather clumsy solution, but it did the trick and there
was no time chasing for a more elegant solution. Maybe somebody on this
list has made a more versatile and elegant solution.

The root cause is that Grails do not address dependent/computed
properties in domain classes particular well. What is needed, is to
associate a sort closure with each such property and then let the
framework do the rest. Similar (but behind the scene) to the snippet above.

    /jens


Jay Goldman skrev:

> i think g:sortableColumn sets the sort param which is used to generate
> the hql used to retrieve the data to display (along with the order,
> offset, and max values).
> that is, these properties are passed to the domain class's list method
> which does a hibernate call
>  
>  So i don't know how it can sort on other than domain data columns.
>  
> I also don't know if you can sort on a property of a one-to-one
> relationship (E.g., a Car has an Owner and you display and want to
> sort on the names of Owners).
>  
> Maybe there is a way to add computed column(s) to the underlying
> hql so they can participate in the selection and ordering of display
> data. Otherwise it seems to me that you would have to fetch all the
> data and sort it 'locally' instead of in the database.
>  
> Hopefully I am wrong and someone will correct me
>  
> jay
>
> ------------------------------------------------------------------------
> *From:* Kenneth Kousen [mailto:[hidden email]]
> *Sent:* Tuesday, December 18, 2007 11:05 AM
> *To:* [hidden email]
> *Subject:* Re: [grails-user] Dependent property in domain class
>
> Yes it did, thanks.  I was able to use that line along with only the
> getter method to establish the property.  I didn't need to put in a
> setter or make "length" an attribute, either.
>
> I tried putting my new property in a <g:sortableColumn> tag in a gsp.  
> While it appeared to work, clicking on it wound up sorting by
> startDate instead.  Any idea what that's all about?
>
> Ken
>
> On 12/18/07, *Robert Fletcher* <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     static transients = ['length']
>
>     Should do the trick, I believe
>
>     On 18/12/2007, Kenneth Kousen <[hidden email]
>     <mailto:[hidden email]>> wrote:
>     > Hi all,
>     >
>     > I have a domain class Course that looks like this:
>     >
>     > class Course {
>     >   String title
>     >   Date startDate
>     >   Date endDate
>     >
>     >   // other properties, toString() method, constraints as usual...
>     > }
>     >
>     > I would like to add a "length" property to Course, which is
>     dependent on the
>     > existing startDate and endDate properties.  Since it's
>     dependent, I don't
>     > want to provide a setter method, nor do I plan to store it in
>     the database.
>     > I tried just adding a getter method
>     >
>     > def getLength() {
>     >   int days = 0
>     >   for (date in startDate..endDate) {
>     >     days++
>     >   }
>     >   return days
>     > }
>     >
>     > but when I start up Grails I get an exception because the length
>     property
>     > has no setter method.
>     >
>     > What's the appropriate way to implement a "read-only" property
>     in a domain
>     > class?  Would some use of the "transient" keyword work?  Should
>     I be
>     > avoiding the domain class altogether and build a separate "view"
>     class, with
>     > the attendant DRY violations?
>     >
>     > Any advice would be appreciated,
>     >
>     > Ken Kousen
>     > --
>     > Kenneth A. Kousen
>     > President
>     > Kousen IT, Inc.
>     >
>     > Email: [hidden email] <mailto:[hidden email]>
>     > Site: http://www.kousenit.com <http://www.kousenit.com>
>     > Blog: http://kousenit.wordpress.com
>
>     ---------------------------------------------------------------------
>     To unsubscribe from this list please visit:
>
>         http://xircles.codehaus.org/manage_email
>
>
>
>
> --
> Kenneth A. Kousen
> President
> Kousen IT, Inc.
>
> Email: [hidden email] <mailto:[hidden email]>
> Site: http://www.kousenit.com
> Blog: http://kousenit.wordpress.com 

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: Dependent property in domain class

Jay Goldman
 
I know i can (theoretically) sort the data in the controller ... but
that's what the database server is for. The data set may be too large to
retrieve to sort outside the database. Hopefully there is an index on
the table to improve performance. In the end you may only want ~10 rows
of data (or whatever your page size is) starting at some offset from the
beginning ... but you have to sort all the data first.
Whereas if you move this processing to the database server it may know
how to sort using an index and moreover will stop generating output when
it has fulfilled the request.

Also, say i want to sort on some attribute of a 1-1 relationship ... not
only do you have to instantiate all of the 'main' table entities but you
also have to create instances of all the related entities ...

Not to mention sorting on multiple columns.

btw, are you are paginating the results?
if so i don't see how this code would work as the list returned by
Foobar.list(params) will not necessarily be the desired data ...
you would have to remove the 'max' and 'offset' values from params
first, and then implement selecting the desired sublist after you do the
sort.

So, i agree with your root cause except the solution is not to add more
processing in the controller but to push more processing to the server
via hibernate. I realize that generating the appropriate hql is not
simple. Since 'display' data or models is typically a de-normalized view
of the underlying relational data i think more work needs to be done in
this area to provide an easy way to create these display models.

Obviously, one can write your own Xxx.executeQuery and process the
results etc but it would be nice if there was a way to add named
computed fields and sort of them in the results.

-jay

-----Original Message-----
From: Jens Riboe [mailto:[hidden email]]
Sent: Wednesday, December 19, 2007 7:39 AM
To: [hidden email]
Subject: Re: [grails-user] Dependent property in domain class

 >>So i don't know how it can sort on other than domain data columns I
had this problem too and solved it by changing the list controller
closure to check for params.sort and then for each non-domain property.
Similar to

def   list = {
    def lst
    switch (params.sort) {
        default:
           lst = Foobar.list(params)
           break
        case 'dependentProperty':
           def sort = params.remove('sort')
           lst = Foobar.list(params).sort { a,b ->
                if (params.order == 'desc') {def t=a; a=b; b=t;}
                return a.dependentProperty <=> b.dependentProperty
            }
           params.sort = sort
           break
    }
    [ foobarList: lst ]
}

I know this is a rather clumsy solution, but it did the trick and there
was no time chasing for a more elegant solution. Maybe somebody on this
list has made a more versatile and elegant solution.

The root cause is that Grails do not address dependent/computed
properties in domain classes particular well. What is needed, is to
associate a sort closure with each such property and then let the
framework do the rest. Similar (but behind the scene) to the snippet
above.

    /jens


Jay Goldman skrev:
> i think g:sortableColumn sets the sort param which is used to generate

> the hql used to retrieve the data to display (along with the order,
> offset, and max values).
> that is, these properties are passed to the domain class's list method

> which does a hibernate call
>  
>  So i don't know how it can sort on other than domain data columns.
>  
> I also don't know if you can sort on a property of a one-to-one
> relationship (E.g., a Car has an Owner and you display and want to
> sort on the names of Owners).
>  
> Maybe there is a way to add computed column(s) to the underlying hql
> so they can participate in the selection and ordering of display data.

> Otherwise it seems to me that you would have to fetch all the data and

> sort it 'locally' instead of in the database.
>  
> Hopefully I am wrong and someone will correct me
>  
> jay
>
> ----------------------------------------------------------------------
> --
> *From:* Kenneth Kousen [mailto:[hidden email]]
> *Sent:* Tuesday, December 18, 2007 11:05 AM
> *To:* [hidden email]
> *Subject:* Re: [grails-user] Dependent property in domain class
>
> Yes it did, thanks.  I was able to use that line along with only the
> getter method to establish the property.  I didn't need to put in a
> setter or make "length" an attribute, either.
>
> I tried putting my new property in a <g:sortableColumn> tag in a gsp.

> While it appeared to work, clicking on it wound up sorting by
> startDate instead.  Any idea what that's all about?
>
> Ken
>
> On 12/18/07, *Robert Fletcher* <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     static transients = ['length']
>
>     Should do the trick, I believe
>
>     On 18/12/2007, Kenneth Kousen <[hidden email]
>     <mailto:[hidden email]>> wrote:
>     > Hi all,
>     >
>     > I have a domain class Course that looks like this:
>     >
>     > class Course {
>     >   String title
>     >   Date startDate
>     >   Date endDate
>     >
>     >   // other properties, toString() method, constraints as
usual...

>     > }
>     >
>     > I would like to add a "length" property to Course, which is
>     dependent on the
>     > existing startDate and endDate properties.  Since it's
>     dependent, I don't
>     > want to provide a setter method, nor do I plan to store it in
>     the database.
>     > I tried just adding a getter method
>     >
>     > def getLength() {
>     >   int days = 0
>     >   for (date in startDate..endDate) {
>     >     days++
>     >   }
>     >   return days
>     > }
>     >
>     > but when I start up Grails I get an exception because the length
>     property
>     > has no setter method.
>     >
>     > What's the appropriate way to implement a "read-only" property
>     in a domain
>     > class?  Would some use of the "transient" keyword work?  Should
>     I be
>     > avoiding the domain class altogether and build a separate "view"
>     class, with
>     > the attendant DRY violations?
>     >
>     > Any advice would be appreciated,
>     >
>     > Ken Kousen
>     > --
>     > Kenneth A. Kousen
>     > President
>     > Kousen IT, Inc.
>     >
>     > Email: [hidden email] <mailto:[hidden email]>
>     > Site: http://www.kousenit.com <http://www.kousenit.com>
>     > Blog: http://kousenit.wordpress.com
>
>
---------------------------------------------------------------------

>     To unsubscribe from this list please visit:
>
>         http://xircles.codehaus.org/manage_email
>
>
>
>
> --
> Kenneth A. Kousen
> President
> Kousen IT, Inc.
>
> Email: [hidden email] <mailto:[hidden email]>
> Site: http://www.kousenit.com
> Blog: http://kousenit.wordpress.com

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Dependent property in domain class

jens.riboe
 >>are you are paginating the results
Nope. This was just a Q&D solution that solved my problem - no
pagination was needed.

 >>sort the data in the controller ... but that's what the database
server is for
Not really, if the data do not originate from the database, which is the
case for dependent/computed properties.

In the example below, there is no way to push the data down to the
database, unless one implements it there which is not on the agenda.
class Cert {
    Date       start
    Date       end
    boolean   revoked

    static transients = ['status', 'valid']

    String      getStatus() {
       if (revoked) return 'revoked'
       Date now = new Date()
       if (now.before(start)) return 'premature'
       if (end.before(now)) return 'expired'
       return 'valid'
    }
    void   setStatus(String s) {}

    boolean  isValid() {
       return this.status == 'valid'
    }
    void   setValid(boolean b) {}
}

    /jens

Jay Goldman skrev:

>  
> I know i can (theoretically) sort the data in the controller ... but
> that's what the database server is for. The data set may be too large to
> retrieve to sort outside the database. Hopefully there is an index on
> the table to improve performance. In the end you may only want ~10 rows
> of data (or whatever your page size is) starting at some offset from the
> beginning ... but you have to sort all the data first.
> Whereas if you move this processing to the database server it may know
> how to sort using an index and moreover will stop generating output when
> it has fulfilled the request.
>
> Also, say i want to sort on some attribute of a 1-1 relationship ... not
> only do you have to instantiate all of the 'main' table entities but you
> also have to create instances of all the related entities ...
>
> Not to mention sorting on multiple columns.
>
> btw, are you are paginating the results?
> if so i don't see how this code would work as the list returned by
> Foobar.list(params) will not necessarily be the desired data ...
> you would have to remove the 'max' and 'offset' values from params
> first, and then implement selecting the desired sublist after you do the
> sort.
>
> So, i agree with your root cause except the solution is not to add more
> processing in the controller but to push more processing to the server
> via hibernate. I realize that generating the appropriate hql is not
> simple. Since 'display' data or models is typically a de-normalized view
> of the underlying relational data i think more work needs to be done in
> this area to provide an easy way to create these display models.
>
> Obviously, one can write your own Xxx.executeQuery and process the
> results etc but it would be nice if there was a way to add named
> computed fields and sort of them in the results.
>
> -jay
>
> -----Original Message-----
> From: Jens Riboe [mailto:[hidden email]]
> Sent: Wednesday, December 19, 2007 7:39 AM
> To: [hidden email]
> Subject: Re: [grails-user] Dependent property in domain class
>
>  >>So i don't know how it can sort on other than domain data columns I
> had this problem too and solved it by changing the list controller
> closure to check for params.sort and then for each non-domain property.
> Similar to
>
> def   list = {
>     def lst
>     switch (params.sort) {
>         default:
>            lst = Foobar.list(params)
>            break
>         case 'dependentProperty':
>            def sort = params.remove('sort')
>            lst = Foobar.list(params).sort { a,b ->
>                 if (params.order == 'desc') {def t=a; a=b; b=t;}
>                 return a.dependentProperty <=> b.dependentProperty
>             }
>            params.sort = sort
>            break
>     }
>     [ foobarList: lst ]
> }
>
> I know this is a rather clumsy solution, but it did the trick and there
> was no time chasing for a more elegant solution. Maybe somebody on this
> list has made a more versatile and elegant solution.
>
> The root cause is that Grails do not address dependent/computed
> properties in domain classes particular well. What is needed, is to
> associate a sort closure with each such property and then let the
> framework do the rest. Similar (but behind the scene) to the snippet
> above.
>
>     /jens
>
>
> Jay Goldman skrev:
>  
>> i think g:sortableColumn sets the sort param which is used to generate
>>    
>
>  
>> the hql used to retrieve the data to display (along with the order,
>> offset, and max values).
>> that is, these properties are passed to the domain class's list method
>>    
>
>  
>> which does a hibernate call
>>  
>>  So i don't know how it can sort on other than domain data columns.
>>  
>> I also don't know if you can sort on a property of a one-to-one
>> relationship (E.g., a Car has an Owner and you display and want to
>> sort on the names of Owners).
>>  
>> Maybe there is a way to add computed column(s) to the underlying hql
>> so they can participate in the selection and ordering of display data.
>>    
>
>  
>> Otherwise it seems to me that you would have to fetch all the data and
>>    
>
>  
>> sort it 'locally' instead of in the database.
>>  
>> Hopefully I am wrong and someone will correct me
>>  
>> jay
>>
>> ----------------------------------------------------------------------
>> --
>> *From:* Kenneth Kousen [mailto:[hidden email]]
>> *Sent:* Tuesday, December 18, 2007 11:05 AM
>> *To:* [hidden email]
>> *Subject:* Re: [grails-user] Dependent property in domain class
>>
>> Yes it did, thanks.  I was able to use that line along with only the
>> getter method to establish the property.  I didn't need to put in a
>> setter or make "length" an attribute, either.
>>
>> I tried putting my new property in a <g:sortableColumn> tag in a gsp.
>>    
>
>  
>> While it appeared to work, clicking on it wound up sorting by
>> startDate instead.  Any idea what that's all about?
>>
>> Ken
>>
>> On 12/18/07, *Robert Fletcher* <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>     static transients = ['length']
>>
>>     Should do the trick, I believe
>>
>>     On 18/12/2007, Kenneth Kousen <[hidden email]
>>     <mailto:[hidden email]>> wrote:
>>     > Hi all,
>>     >
>>     > I have a domain class Course that looks like this:
>>     >
>>     > class Course {
>>     >   String title
>>     >   Date startDate
>>     >   Date endDate
>>     >
>>     >   // other properties, toString() method, constraints as
>>    
> usual...
>  
>>     > }
>>     >
>>     > I would like to add a "length" property to Course, which is
>>     dependent on the
>>     > existing startDate and endDate properties.  Since it's
>>     dependent, I don't
>>     > want to provide a setter method, nor do I plan to store it in
>>     the database.
>>     > I tried just adding a getter method
>>     >
>>     > def getLength() {
>>     >   int days = 0
>>     >   for (date in startDate..endDate) {
>>     >     days++
>>     >   }
>>     >   return days
>>     > }
>>     >
>>     > but when I start up Grails I get an exception because the length
>>     property
>>     > has no setter method.
>>     >
>>     > What's the appropriate way to implement a "read-only" property
>>     in a domain
>>     > class?  Would some use of the "transient" keyword work?  Should
>>     I be
>>     > avoiding the domain class altogether and build a separate "view"
>>     class, with
>>     > the attendant DRY violations?
>>     >
>>     > Any advice would be appreciated,
>>     >
>>     > Ken Kousen
>>     > --
>>     > Kenneth A. Kousen
>>     > President
>>     > Kousen IT, Inc.
>>     >
>>     > Email: [hidden email] <mailto:[hidden email]>
>>     > Site: http://www.kousenit.com <http://www.kousenit.com>
>>     > Blog: http://kousenit.wordpress.com
>>
>>
>>    
> ---------------------------------------------------------------------
>  
>>     To unsubscribe from this list please visit:
>>
>>         http://xircles.codehaus.org/manage_email
>>
>>
>>
>>
>> --
>> Kenneth A. Kousen
>> President
>> Kousen IT, Inc.
>>
>> Email: [hidden email] <mailto:[hidden email]>
>> Site: http://www.kousenit.com
>> Blog: http://kousenit.wordpress.com
>>    
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>  

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: Dependent property in domain class

Jay Goldman
I was assuming that the dependent/computed properties were computed from
database data, which means a trip to the db server and it may have been
possible for it to do all the computation for you.

My point was that unless the db server knows about these dependent
properties at least during query processing it can't possibly help doing
pagination.

If you are not paginating i guess it doesn't much matter where sorting
by computed values is done



-----Original Message-----
From: Jens Riboe [mailto:[hidden email]]
Sent: Wednesday, December 19, 2007 2:39 PM
To: [hidden email]
Subject: Re: [grails-user] Dependent property in domain class

 >>are you are paginating the results
Nope. This was just a Q&D solution that solved my problem - no
pagination was needed.

 >>sort the data in the controller ... but that's what the database
server is for Not really, if the data do not originate from the
database, which is the case for dependent/computed properties.

In the example below, there is no way to push the data down to the
database, unless one implements it there which is not on the agenda.
class Cert {
    Date       start
    Date       end
    boolean   revoked

    static transients = ['status', 'valid']

    String      getStatus() {
       if (revoked) return 'revoked'
       Date now = new Date()
       if (now.before(start)) return 'premature'
       if (end.before(now)) return 'expired'
       return 'valid'
    }
    void   setStatus(String s) {}

    boolean  isValid() {
       return this.status == 'valid'
    }
    void   setValid(boolean b) {}
}

    /jens

Jay Goldman skrev:
>  
> I know i can (theoretically) sort the data in the controller ... but
> that's what the database server is for. The data set may be too large
> to retrieve to sort outside the database. Hopefully there is an index
> on the table to improve performance. In the end you may only want ~10
> rows of data (or whatever your page size is) starting at some offset
> from the beginning ... but you have to sort all the data first.
> Whereas if you move this processing to the database server it may know

> how to sort using an index and moreover will stop generating output
> when it has fulfilled the request.
>
> Also, say i want to sort on some attribute of a 1-1 relationship ...
> not only do you have to instantiate all of the 'main' table entities
> but you also have to create instances of all the related entities ...
>
> Not to mention sorting on multiple columns.
>
> btw, are you are paginating the results?
> if so i don't see how this code would work as the list returned by
> Foobar.list(params) will not necessarily be the desired data ...
> you would have to remove the 'max' and 'offset' values from params
> first, and then implement selecting the desired sublist after you do
> the sort.
>
> So, i agree with your root cause except the solution is not to add
> more processing in the controller but to push more processing to the
> server via hibernate. I realize that generating the appropriate hql is

> not simple. Since 'display' data or models is typically a
> de-normalized view of the underlying relational data i think more work

> needs to be done in this area to provide an easy way to create these
display models.

>
> Obviously, one can write your own Xxx.executeQuery and process the
> results etc but it would be nice if there was a way to add named
> computed fields and sort of them in the results.
>
> -jay
>
> -----Original Message-----
> From: Jens Riboe [mailto:[hidden email]]
> Sent: Wednesday, December 19, 2007 7:39 AM
> To: [hidden email]
> Subject: Re: [grails-user] Dependent property in domain class
>
>  >>So i don't know how it can sort on other than domain data columns I

> had this problem too and solved it by changing the list controller
> closure to check for params.sort and then for each non-domain
property.

> Similar to
>
> def   list = {
>     def lst
>     switch (params.sort) {
>         default:
>            lst = Foobar.list(params)
>            break
>         case 'dependentProperty':
>            def sort = params.remove('sort')
>            lst = Foobar.list(params).sort { a,b ->
>                 if (params.order == 'desc') {def t=a; a=b; b=t;}
>                 return a.dependentProperty <=> b.dependentProperty
>             }
>            params.sort = sort
>            break
>     }
>     [ foobarList: lst ]
> }
>
> I know this is a rather clumsy solution, but it did the trick and
> there was no time chasing for a more elegant solution. Maybe somebody
> on this list has made a more versatile and elegant solution.
>
> The root cause is that Grails do not address dependent/computed
> properties in domain classes particular well. What is needed, is to
> associate a sort closure with each such property and then let the
> framework do the rest. Similar (but behind the scene) to the snippet
> above.
>
>     /jens
>
>
> Jay Goldman skrev:
>  
>> i think g:sortableColumn sets the sort param which is used to
>> generate
>>    
>
>  
>> the hql used to retrieve the data to display (along with the order,
>> offset, and max values).
>> that is, these properties are passed to the domain class's list
>> method
>>    
>
>  
>> which does a hibernate call
>>  
>>  So i don't know how it can sort on other than domain data columns.
>>  
>> I also don't know if you can sort on a property of a one-to-one
>> relationship (E.g., a Car has an Owner and you display and want to
>> sort on the names of Owners).
>>  
>> Maybe there is a way to add computed column(s) to the underlying hql
>> so they can participate in the selection and ordering of display
data.

>>    
>
>  
>> Otherwise it seems to me that you would have to fetch all the data
>> and
>>    
>
>  
>> sort it 'locally' instead of in the database.
>>  
>> Hopefully I am wrong and someone will correct me
>>  
>> jay
>>
>> ---------------------------------------------------------------------
>> -
>> --
>> *From:* Kenneth Kousen [mailto:[hidden email]]
>> *Sent:* Tuesday, December 18, 2007 11:05 AM
>> *To:* [hidden email]
>> *Subject:* Re: [grails-user] Dependent property in domain class
>>
>> Yes it did, thanks.  I was able to use that line along with only the
>> getter method to establish the property.  I didn't need to put in a
>> setter or make "length" an attribute, either.
>>
>> I tried putting my new property in a <g:sortableColumn> tag in a gsp.
>>    
>
>  
>> While it appeared to work, clicking on it wound up sorting by
>> startDate instead.  Any idea what that's all about?
>>
>> Ken
>>
>> On 12/18/07, *Robert Fletcher* <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>     static transients = ['length']
>>
>>     Should do the trick, I believe
>>
>>     On 18/12/2007, Kenneth Kousen <[hidden email]
>>     <mailto:[hidden email]>> wrote:
>>     > Hi all,
>>     >
>>     > I have a domain class Course that looks like this:
>>     >
>>     > class Course {
>>     >   String title
>>     >   Date startDate
>>     >   Date endDate
>>     >
>>     >   // other properties, toString() method, constraints as
>>    
> usual...
>  
>>     > }
>>     >
>>     > I would like to add a "length" property to Course, which is
>>     dependent on the
>>     > existing startDate and endDate properties.  Since it's
>>     dependent, I don't
>>     > want to provide a setter method, nor do I plan to store it in
>>     the database.
>>     > I tried just adding a getter method
>>     >
>>     > def getLength() {
>>     >   int days = 0
>>     >   for (date in startDate..endDate) {
>>     >     days++
>>     >   }
>>     >   return days
>>     > }
>>     >
>>     > but when I start up Grails I get an exception because the
length
>>     property
>>     > has no setter method.
>>     >
>>     > What's the appropriate way to implement a "read-only" property
>>     in a domain
>>     > class?  Would some use of the "transient" keyword work?  Should
>>     I be
>>     > avoiding the domain class altogether and build a separate
"view"

>>     class, with
>>     > the attendant DRY violations?
>>     >
>>     > Any advice would be appreciated,
>>     >
>>     > Ken Kousen
>>     > --
>>     > Kenneth A. Kousen
>>     > President
>>     > Kousen IT, Inc.
>>     >
>>     > Email: [hidden email] <mailto:[hidden email]>
>>     > Site: http://www.kousenit.com <http://www.kousenit.com>
>>     > Blog: http://kousenit.wordpress.com
>>
>>
>>    
> ---------------------------------------------------------------------
>  
>>     To unsubscribe from this list please visit:
>>
>>         http://xircles.codehaus.org/manage_email
>>
>>
>>
>>
>> --
>> Kenneth A. Kousen
>> President
>> Kousen IT, Inc.
>>
>> Email: [hidden email] <mailto:[hidden email]>
>> Site: http://www.kousenit.com
>> Blog: http://kousenit.wordpress.com
>>    
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>  

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email