Discussion:
are new Enums in gorm safe?
Kallin Nagelberg
2008-06-06 19:09:07 UTC
Permalink
I just implemented a new domain class with the built in Enum support of
grails 1.3.
Looking at the schema in my hsqldb, it's just using integers to store them.
I'm concerned that if I was to reorder the enums in my source, that gorm
would start to pick up the wrong enums.
Is this concern valid, or has this been taken care of ?
Ilo Som
2008-06-06 21:34:52 UTC
Permalink
First of all- thanks to Graeme and the other committers. Great work
and lovely new features in 1.0.3.

I couldn't wait, just upgraded my app to 1.0.3 and integrated some
enums. Here's my observation:

> Looking at the schema in my hsqldb, it's just using integers to store them.
> I'm concerned that if I was to reorder the enums in my source, that gorm
> would start to pick up the wrong enums.
> Is this concern valid, or has this been taken care of ?

That's right. GORM maps to integers by default. Reordering the enums
messes up availalbe db data.
I'm wondering why Grails implement the integer mapping and not using
Hibernates "EnumType.STRING"?
From my point of view the usage of the enum-name would be more save
and also much cleaner when querying data in the database.

Is there a way to change the default behavior (use enum strings
instead of ordinals)?
Or could it be changed in the mapping closure for a specific property?

Another thing I just detected:

Set your enum property to nullable:true. Use scaffolding to generate
standard controller/view for your domain object. Use the 'create'
view.
When you select an empty value for the enum property you get an
"Failed to convert property value of type [java.lang.String] to
required type .[enumType] .... no matching editors or conversion
strategy found"

What is the simplest way to make this work?

Cheers Ilo

On Fri, Jun 6, 2008 at 9:09 PM, Kallin Nagelberg
<***@gmail.com> wrote:
> I just implemented a new domain class with the built in Enum support of
> grails 1.3.
> Looking at the schema in my hsqldb, it's just using integers to store them.
> I'm concerned that if I was to reorder the enums in my source, that gorm
> would start to pick up the wrong enums.
> Is this concern valid, or has this been taken care of ?
>

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

http://xircles.codehaus.org/manage_email
Robert Fletcher
2008-06-07 13:34:12 UTC
Permalink
On Fri, Jun 6, 2008 at 10:34 PM, Ilo Som <***@gmail.com> wrote:
>
> Is there a way to change the default behavior (use enum strings
> instead of ordinals)?
> Or could it be changed in the mapping closure for a specific property?
>

Unfortunately the "type" mapping you can set on a domain object has to
be a subclass of org.hibernate.usertype.UserType which EnumType is
not, it's part of the JPA annotations API. Not sure if there's another
way to coerce this behaviour.

EnumType.ORDINAL is the default in Hibernate and I guess Grails is
just following that which is a shame as it was never a good default,
in fact it's hard to think of any reason why it would ever be a good
choice over EnumType.STRING.

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

http://xircles.codehaus.org/manage_email
Robert Fletcher
2008-06-07 14:05:51 UTC
Permalink
After a little digging it appears GORM uses
org.hibernate.type.EnumType to map to the table, (not the same
EnumType that supplies the STRING and ORDINAL constants - this one
*is* a subclass of UserType). It looks like that class tries to figure
out whether the enum has been persisted as an ordinal or a string
value based on the column type it finds. I *think* if the column is
defined as VARCHAR (i.e. don't let Grails create your table - do it
manually) it ought to work, however I can't see a way to get Grails to
do this automatically. Mapping my field to type: 'string' didn't work.

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

http://xircles.codehaus.org/manage_email
Ilo Som
2008-06-08 08:53:04 UTC
Permalink
Thanks Robert.
Did some GORM committer read this and could give some explanations why
Grails isn't more flexible here?
It's a pity if there isn't any way to map enums to string.

What is about the data binding problem of empty strings to enums?
---
Set your enum property to nullable:true. Use scaffolding to generate
standard controller/view for your domain object. Use the 'create'
view.
When you select an empty value for the enum property you get an
"Failed to convert property value of type [java.lang.String] to
required type .[enumType] .... no matching editors or conversion
strategy found"

What is the simplest way to make this work?
---

On Sat, Jun 7, 2008 at 4:05 PM, Robert Fletcher
<***@googlemail.com> wrote:
> After a little digging it appears GORM uses
> org.hibernate.type.EnumType to map to the table, (not the same
> EnumType that supplies the STRING and ORDINAL constants - this one
> *is* a subclass of UserType). It looks like that class tries to figure
> out whether the enum has been persisted as an ordinal or a string
> value based on the column type it finds. I *think* if the column is
> defined as VARCHAR (i.e. don't let Grails create your table - do it
> manually) it ought to work, however I can't see a way to get Grails to
> do this automatically. Mapping my field to type: 'string' didn't work.
>
> ---------------------------------------------------------------------
> 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
Graeme Rocher
2008-06-08 09:57:37 UTC
Permalink
We currently just follow the Hibernate default which is to use the
Hibernate EnumType which defaults to ordinal values. If you want more
flexibility feel free to raise feature requests

Cheers

On Sun, Jun 8, 2008 at 9:53 AM, Ilo Som <***@gmail.com> wrote:
> Thanks Robert.
> Did some GORM committer read this and could give some explanations why
> Grails isn't more flexible here?
> It's a pity if there isn't any way to map enums to string.
>
> What is about the data binding problem of empty strings to enums?
> ---
> Set your enum property to nullable:true. Use scaffolding to generate
> standard controller/view for your domain object. Use the 'create'
> view.
> When you select an empty value for the enum property you get an
> "Failed to convert property value of type [java.lang.String] to
> required type .[enumType] .... no matching editors or conversion
> strategy found"
>
> What is the simplest way to make this work?
> ---
>
> On Sat, Jun 7, 2008 at 4:05 PM, Robert Fletcher
> <***@googlemail.com> wrote:
>> After a little digging it appears GORM uses
>> org.hibernate.type.EnumType to map to the table, (not the same
>> EnumType that supplies the STRING and ORDINAL constants - this one
>> *is* a subclass of UserType). It looks like that class tries to figure
>> out whether the enum has been persisted as an ordinal or a string
>> value based on the column type it finds. I *think* if the column is
>> defined as VARCHAR (i.e. don't let Grails create your table - do it
>> manually) it ought to work, however I can't see a way to get Grails to
>> do this automatically. Mapping my field to type: 'string' didn't work.
>>
>> ---------------------------------------------------------------------
>> 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
>
>
>



--
Graeme Rocher
Grails Project Lead
G2One, Inc. Chief Technology Officer
http://www.g2one.com

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

http://xircles.codehaus.org/manage_email
Ilo Som
2008-06-08 15:42:22 UTC
Permalink
ok, thanks:
http://jira.codehaus.org/browse/GRAILS-3076
http://jira.codehaus.org/browse/GRAILS-3077 (could be a bug and not a
feature-request?)

On Sun, Jun 8, 2008 at 11:57 AM, Graeme Rocher <***@g2one.com> wrote:
> We currently just follow the Hibernate default which is to use the
> Hibernate EnumType which defaults to ordinal values. If you want more
> flexibility feel free to raise feature requests
>
> Cheers
>
> On Sun, Jun 8, 2008 at 9:53 AM, Ilo Som <***@gmail.com> wrote:
>> Thanks Robert.
>> Did some GORM committer read this and could give some explanations why
>> Grails isn't more flexible here?
>> It's a pity if there isn't any way to map enums to string.
>>
>> What is about the data binding problem of empty strings to enums?
>> ---
>> Set your enum property to nullable:true. Use scaffolding to generate
>> standard controller/view for your domain object. Use the 'create'
>> view.
>> When you select an empty value for the enum property you get an
>> "Failed to convert property value of type [java.lang.String] to
>> required type .[enumType] .... no matching editors or conversion
>> strategy found"
>>
>> What is the simplest way to make this work?
>> ---
>>
>> On Sat, Jun 7, 2008 at 4:05 PM, Robert Fletcher
>> <***@googlemail.com> wrote:
>>> After a little digging it appears GORM uses
>>> org.hibernate.type.EnumType to map to the table, (not the same
>>> EnumType that supplies the STRING and ORDINAL constants - this one
>>> *is* a subclass of UserType). It looks like that class tries to figure
>>> out whether the enum has been persisted as an ordinal or a string
>>> value based on the column type it finds. I *think* if the column is
>>> defined as VARCHAR (i.e. don't let Grails create your table - do it
>>> manually) it ought to work, however I can't see a way to get Grails to
>>> do this automatically. Mapping my field to type: 'string' didn't work.
>>>
>>> ---------------------------------------------------------------------
>>> 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
>>
>>
>>
>
>
>
> --
> Graeme Rocher
> Grails Project Lead
> G2One, Inc. Chief Technology Officer
> http://www.g2one.com
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
> http://xircles.codehaus.org/manage_email
>
>
>



--
Cheers Ilo

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

http://xircles.codehaus.org/manage_email
Matt Lentzner
2008-07-16 18:01:21 UTC
Permalink
I've been giving this a lot of thought. Using ordinals is a disaster waiting
to happen, but being able to save the values as integers has merit. Saving
strings is pretty wasteful since the same string will be repeated in the
database many times and you get into a potential conflict situation where
readability of the enum name conflicts with not wanting to have a long
string stored repetitively in the database.

The nicest way to resolve the enums would be to be able to assign int values
to each as opposed to getting the ordinal. If we could write the type
resolver to look for a getId() call and then fall back to ordinal() this
would work well. Ideally, you would want to implement the getId() method,
but if you didn't you could retrofit at any time later by assigning the
current ordinal values and essentially locking them in. Conceptually, the
getId() dovetails nicely with foreign key behavior in the SQL database.

I also attempted to override the ordinal behavior in the Enum in order to
assign values, but I couldn't get it to work. I kept getting threading
errors. If anyone has any advice as to where I can do the override
(monkeypatch?) I'd love to hear about it. I don't think that this would have
any ramifications for the proper behavior of Enum, since the ordinal values
are completely arbitrary. I wouldn't be surprised if they were even required
to be contiguous. Of course that needs to be tested, but I need a working
implementation of that patch first.

Cheers,

Matt





Ilo Som wrote:
>
> ok, thanks:
> http://jira.codehaus.org/browse/GRAILS-3076
> http://jira.codehaus.org/browse/GRAILS-3077 (could be a bug and not a
> feature-request?)
>
> On Sun, Jun 8, 2008 at 11:57 AM, Graeme Rocher <***@g2one.com> wrote:
>> We currently just follow the Hibernate default which is to use the
>> Hibernate EnumType which defaults to ordinal values. If you want more
>> flexibility feel free to raise feature requests
>>
>> Cheers
>>
>> On Sun, Jun 8, 2008 at 9:53 AM, Ilo Som <***@gmail.com> wrote:
>>> Thanks Robert.
>>> Did some GORM committer read this and could give some explanations why
>>> Grails isn't more flexible here?
>>> It's a pity if there isn't any way to map enums to string.
>>>
>>> What is about the data binding problem of empty strings to enums?
>>> ---
>>> Set your enum property to nullable:true. Use scaffolding to generate
>>> standard controller/view for your domain object. Use the 'create'
>>> view.
>>> When you select an empty value for the enum property you get an
>>> "Failed to convert property value of type [java.lang.String] to
>>> required type .[enumType] .... no matching editors or conversion
>>> strategy found"
>>>
>>> What is the simplest way to make this work?
>>> ---
>>>
>>> On Sat, Jun 7, 2008 at 4:05 PM, Robert Fletcher
>>> <***@googlemail.com> wrote:
>>>> After a little digging it appears GORM uses
>>>> org.hibernate.type.EnumType to map to the table, (not the same
>>>> EnumType that supplies the STRING and ORDINAL constants - this one
>>>> *is* a subclass of UserType). It looks like that class tries to figure
>>>> out whether the enum has been persisted as an ordinal or a string
>>>> value based on the column type it finds. I *think* if the column is
>>>> defined as VARCHAR (i.e. don't let Grails create your table - do it
>>>> manually) it ought to work, however I can't see a way to get Grails to
>>>> do this automatically. Mapping my field to type: 'string' didn't work.
>>>>
>>>> ---------------------------------------------------------------------
>>>> 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
>>>
>>>
>>>
>>
>>
>>
>> --
>> Graeme Rocher
>> Grails Project Lead
>> G2One, Inc. Chief Technology Officer
>> http://www.g2one.com
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>> http://xircles.codehaus.org/manage_email
>>
>>
>>
>
>
>
> --
> Cheers Ilo
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
> http://xircles.codehaus.org/manage_email
>
>
>
>

--
View this message in context: http://www.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p18493231.html
Sent from the grails - user mailing list archive at Nabble.com.


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

http://xircles.codehaus.org/manage_email
Robert Fletcher
2008-07-17 08:20:41 UTC
Permalink
That smacks to me of premature optimisation. Is it really such an
issue to have enums stored as String values? From a purist point of
view, sure it's somewhat wasteful but I'd argue that's considerably
outweighed by the convenience and simplicity. Most enum names tend to
be pretty short. Plus it makes the results of any database queries you
may do directly considerably more readable. Using assigned int values
for enums seems like a half-step back towards the int constant
anti-pattern enums were introduced to solve in the first place. If
storing the same string multiple times is really a concern you could
always promote the enum to a simple GORM class and use a one-to-one
association.

Cheers,
Rob

On Wed, Jul 16, 2008 at 7:01 PM, Matt Lentzner <***@gmail.com> wrote:
>
> I've been giving this a lot of thought. Using ordinals is a disaster waiting
> to happen, but being able to save the values as integers has merit. Saving
> strings is pretty wasteful since the same string will be repeated in the
> database many times and you get into a potential conflict situation where
> readability of the enum name conflicts with not wanting to have a long
> string stored repetitively in the database.
>
> The nicest way to resolve the enums would be to be able to assign int values
> to each as opposed to getting the ordinal. If we could write the type
> resolver to look for a getId() call and then fall back to ordinal() this
> would work well. Ideally, you would want to implement the getId() method,
> but if you didn't you could retrofit at any time later by assigning the
> current ordinal values and essentially locking them in. Conceptually, the
> getId() dovetails nicely with foreign key behavior in the SQL database.
>
> I also attempted to override the ordinal behavior in the Enum in order to
> assign values, but I couldn't get it to work. I kept getting threading
> errors. If anyone has any advice as to where I can do the override
> (monkeypatch?) I'd love to hear about it. I don't think that this would have
> any ramifications for the proper behavior of Enum, since the ordinal values
> are completely arbitrary. I wouldn't be surprised if they were even required
> to be contiguous. Of course that needs to be tested, but I need a working
> implementation of that patch first.
>
> Cheers,
>
> Matt
>

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

http://xircles.codehaus.org/manage_email
Matt Lentzner
2008-07-17 17:05:26 UTC
Permalink
Robert,

I agree with you that storing a String value is nice as far a db readability
goes, but there are other costs with that approach besides storage that I
did not cover. When you say "String" you're really talking about the name
property. As soon as you store that in the database then you cannot easily
refactor that name value. We all know that the rename refactor is the most
common kind of refactoring - so that would bite you sooner or later. It
conflates the representation of the object in the database with the name it
has in the code. This is similar to using the ordinal value (although I
admit, not nearly as bad).

There's a reason that foreign keys are abstract row ids. People have tried
other approaches and got seriously caught up in their underwear. Maybe the
essence of Enums makes that kind of concern unrealistic, but I would want a
solution that is as general as possible, but keep in mind that we are, in
essence, storing pointers. It violates database normalization as well as
DRY.

There also a question of data integrity. Int fields can be easily set so
that no illegal values can be entered. A String on the other hand could have
all sorts of illegal values put in it and there's no way to enforce data
integrity at the database level. I know some (not all, AIUI) databases
support enums, but then you're dealing with the vagaries of different db
vendors instead of the general case. I personally don't want to go there.

I like the getId() call because it is abstracted, efficient, and should be
easy to retrofit. I would think that Grails could just intercept the ordinal
call from Hibernate and you're done. Hacky, yes, but fairly non-invasive. I
wouldn't be averse to having a String based option to store the enum as
well, but now we're getting into a lot of new code and possible
kitchensinkism.

My final remark is that your example of regressing back to int const enums
is a red herring. The problem wasn't that they were ints, but that they were
not type safe. You could have enums as Strings and the problem would be no
different (with additional problems included). Once you store a value in the
database you lose all type safety anyway so a int is not different from a
String in that regard. The sole benefit to storing the String is db
readability. I think the price tag on that benefit is rather high.

Regards,

Matt


Robert Fletcher wrote:
>
> That smacks to me of premature optimisation. Is it really such an
> issue to have enums stored as String values? From a purist point of
> view, sure it's somewhat wasteful but I'd argue that's considerably
> outweighed by the convenience and simplicity. Most enum names tend to
> be pretty short. Plus it makes the results of any database queries you
> may do directly considerably more readable. Using assigned int values
> for enums seems like a half-step back towards the int constant
> anti-pattern enums were introduced to solve in the first place. If
> storing the same string multiple times is really a concern you could
> always promote the enum to a simple GORM class and use a one-to-one
> association.
>
> Cheers,
> Rob
>
> On Wed, Jul 16, 2008 at 7:01 PM, Matt Lentzner <***@gmail.com>
> wrote:
>>
>> I've been giving this a lot of thought. Using ordinals is a disaster
>> waiting
>> to happen, but being able to save the values as integers has merit.
>> Saving
>> strings is pretty wasteful since the same string will be repeated in the
>> database many times and you get into a potential conflict situation where
>> readability of the enum name conflicts with not wanting to have a long
>> string stored repetitively in the database.
>>
>> The nicest way to resolve the enums would be to be able to assign int
>> values
>> to each as opposed to getting the ordinal. If we could write the type
>> resolver to look for a getId() call and then fall back to ordinal() this
>> would work well. Ideally, you would want to implement the getId() method,
>> but if you didn't you could retrofit at any time later by assigning the
>> current ordinal values and essentially locking them in. Conceptually, the
>> getId() dovetails nicely with foreign key behavior in the SQL database.
>>
>> I also attempted to override the ordinal behavior in the Enum in order to
>> assign values, but I couldn't get it to work. I kept getting threading
>> errors. If anyone has any advice as to where I can do the override
>> (monkeypatch?) I'd love to hear about it. I don't think that this would
>> have
>> any ramifications for the proper behavior of Enum, since the ordinal
>> values
>> are completely arbitrary. I wouldn't be surprised if they were even
>> required
>> to be contiguous. Of course that needs to be tested, but I need a working
>> implementation of that patch first.
>>
>> Cheers,
>>
>> Matt
>>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
> http://xircles.codehaus.org/manage_email
>
>
>
>

--
View this message in context: http://www.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p18513303.html
Sent from the grails - user mailing list archive at Nabble.com.


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

http://xircles.codehaus.org/manage_email
Daniel Honig
2008-07-17 17:49:20 UTC
Permalink
I don't think there is any perfect approach. Strings? how hard is an
update statement in SQL to find occurences of that string and update
it?

I can live with that.
and I love the caught up in their undewear phrase. Matt++
On Thu, Jul 17, 2008 at 1:05 PM, Matt Lentzner <***@gmail.com> wrote:
>
> Robert,
>
> I agree with you that storing a String value is nice as far a db readability
> goes, but there are other costs with that approach besides storage that I
> did not cover. When you say "String" you're really talking about the name
> property. As soon as you store that in the database then you cannot easily
> refactor that name value. We all know that the rename refactor is the most
> common kind of refactoring - so that would bite you sooner or later. It
> conflates the representation of the object in the database with the name it
> has in the code. This is similar to using the ordinal value (although I
> admit, not nearly as bad).
>
> There's a reason that foreign keys are abstract row ids. People have tried
> other approaches and got seriously caught up in their underwear. Maybe the
> essence of Enums makes that kind of concern unrealistic, but I would want a
> solution that is as general as possible, but keep in mind that we are, in
> essence, storing pointers. It violates database normalization as well as
> DRY.
>
> There also a question of data integrity. Int fields can be easily set so
> that no illegal values can be entered. A String on the other hand could have
> all sorts of illegal values put in it and there's no way to enforce data
> integrity at the database level. I know some (not all, AIUI) databases
> support enums, but then you're dealing with the vagaries of different db
> vendors instead of the general case. I personally don't want to go there.
>
> I like the getId() call because it is abstracted, efficient, and should be
> easy to retrofit. I would think that Grails could just intercept the ordinal
> call from Hibernate and you're done. Hacky, yes, but fairly non-invasive. I
> wouldn't be averse to having a String based option to store the enum as
> well, but now we're getting into a lot of new code and possible
> kitchensinkism.
>
> My final remark is that your example of regressing back to int const enums
> is a red herring. The problem wasn't that they were ints, but that they were
> not type safe. You could have enums as Strings and the problem would be no
> different (with additional problems included). Once you store a value in the
> database you lose all type safety anyway so a int is not different from a
> String in that regard. The sole benefit to storing the String is db
> readability. I think the price tag on that benefit is rather high.
>
> Regards,
>
> Matt
>
>
> Robert Fletcher wrote:
>>
>> That smacks to me of premature optimisation. Is it really such an
>> issue to have enums stored as String values? From a purist point of
>> view, sure it's somewhat wasteful but I'd argue that's considerably
>> outweighed by the convenience and simplicity. Most enum names tend to
>> be pretty short. Plus it makes the results of any database queries you
>> may do directly considerably more readable. Using assigned int values
>> for enums seems like a half-step back towards the int constant
>> anti-pattern enums were introduced to solve in the first place. If
>> storing the same string multiple times is really a concern you could
>> always promote the enum to a simple GORM class and use a one-to-one
>> association.
>>
>> Cheers,
>> Rob
>>
>> On Wed, Jul 16, 2008 at 7:01 PM, Matt Lentzner <***@gmail.com>
>> wrote:
>>>
>>> I've been giving this a lot of thought. Using ordinals is a disaster
>>> waiting
>>> to happen, but being able to save the values as integers has merit.
>>> Saving
>>> strings is pretty wasteful since the same string will be repeated in the
>>> database many times and you get into a potential conflict situation where
>>> readability of the enum name conflicts with not wanting to have a long
>>> string stored repetitively in the database.
>>>
>>> The nicest way to resolve the enums would be to be able to assign int
>>> values
>>> to each as opposed to getting the ordinal. If we could write the type
>>> resolver to look for a getId() call and then fall back to ordinal() this
>>> would work well. Ideally, you would want to implement the getId() method,
>>> but if you didn't you could retrofit at any time later by assigning the
>>> current ordinal values and essentially locking them in. Conceptually, the
>>> getId() dovetails nicely with foreign key behavior in the SQL database.
>>>
>>> I also attempted to override the ordinal behavior in the Enum in order to
>>> assign values, but I couldn't get it to work. I kept getting threading
>>> errors. If anyone has any advice as to where I can do the override
>>> (monkeypatch?) I'd love to hear about it. I don't think that this would
>>> have
>>> any ramifications for the proper behavior of Enum, since the ordinal
>>> values
>>> are completely arbitrary. I wouldn't be surprised if they were even
>>> required
>>> to be contiguous. Of course that needs to be tested, but I need a working
>>> implementation of that patch first.
>>>
>>> Cheers,
>>>
>>> Matt
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>> http://xircles.codehaus.org/manage_email
>>
>>
>>
>>
>
> --
> View this message in context: http://www.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p18513303.html
> Sent from the grails - user mailing list archive at Nabble.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
Robert Fletcher
2008-07-18 11:31:11 UTC
Permalink
We're using the liquibase plugin & that kind of refactoring is pretty
common. If your test coverage is good it's absolutely nothing to worry
about.

Matt, I can see your point, I'd just question whether the benefit is
really worth the investment in time of implementation, the overhead of
ensuring it's applied to every enum class in your project, etc.

Cheers,
Rob

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

http://xircles.codehaus.org/manage_email
McGSoftware
2008-11-25 00:01:07 UTC
Permalink
Question & comment:

Is there a way for GORM to map to dbms (MySQL) that has native sql enum
support?
Using strings for the enum values to/from SQL is much betta for reporting,
hand sql and ETL ops.

public enum UserStatus {Invalid, Active, Terminated}

class Person {
... other properties removed...
String name
UserStatus status

static mapping = {
table 'person2'
}
}

For example:
CREATE TABLE IF NOT EXISTS person (
... other fields not shown...
name varchar(35) UNIQUE NOT NULL
COMMENT 'The persons name" )',
status ENUM('Invalid', 'Active', 'Terminated') NOT NULL DEFAULT 'Active'
COMMENT 'Status of this person from systemic perspective'
)ENGINE=InnoDB;

The current impl I tried seems to use enum ordinal values, which is has
proven to be dangerous from a maintenance / production data perspective in
my experience.

If we *must* map to integer values (which is not preferable for MySQL), I'd
prefer to force
the developer to manually set the integer values. Otherwise, a simple enum
value
refactoring could eventually cause a nightmare in your production data.

For example, if a developer accidentally reorders enums in the declarations,
adds a new enum value
in the middle, etc. Unit tests often show no errors (if new data is
generated for the test itself), but
when pushed to production, the new enum int values now get mixed up with the
old enum int values causing a nasty problem that is very difficult to
unravel after you finally discover it and users have
already been creating/updating data.

// Manual enum map. Now you can rename enums, add and remove them
// without breaking production data - as long as they are unique
// numbers.
public enum UserStatus implements EnumMapValue {
Invalid{ public int dbmsValue() { return 1; }},
Active { public int dbmsValue() { return 5; }},
Terminated { public int dbmsValue() { return 10; }};
}

// Framework enum mapping (optional) for those wanting to avoid the enum
// ordinal mapping nightmare against production databases. Requires
// developers to manually assign int value for each enum value.
public interface EnumMapValue {
public int dbmsValue();
}


--
View this message in context: http://www.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p20672667.html
Sent from the grails - user mailing list archive at Nabble.com.


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

http://xircles.codehaus.org/manage_email
mbjarland
2009-03-04 16:31:59 UTC
Permalink
Seems that later versions of grails (1.1?) have implemented a "myEnum
enumType: 'string'" which as far as I can understand uses the name of the
enum for storage. So it seems that enums can now be stored with either
ordinal numbers as ints int the database or with the enum name string.

I would however add a vote for a more flexible approach (such as an optional
getDbValue method which as been suggested). I have a scenario with a
complex, multi-system (i.e. my project is not the only one using the db),
existing legacy database. In other words, migrations are out of the
question, the enum is mapped the way it's mapped and I have no say. In my
case the enum _is_ integer mapped which is good, but is not mapped in
ordinal order but rather with integers such as 100, 200, 5000 etc.

So with the ordinal approach I would have to create an enum with 100 bogus
entries in the beginning, then one proper value, 100 more bogus values, etc.
I think we can all agree that that would stink in a major way.

So I can agree with all previous opinions on the readability of strings and
on the better normalization and space optimization of integers, but that's
only for scenarios where grails is the master of the database schema. In my
scenario the issue is no longer one of performance or how pretty the code
looks, it's simply not a workable solution.

So vote++ for an optional extra method on our grails enums. Say we had:

public enum Sex {
Male(100),
Female(200)

int dbValue

private Sex(dbValue) {
this.dbValue = dbValue;
}

public int getDbValue() {
return value
}
}

this would make the enum fully customizable. If the getDbValue returns a
String, the column would be a string type, if it returns an int, the column
would be an int, this would support all (that I can think of) versions of
weird legacy mappings of string and ints, it would solve the
reordering-your-enums problem, the rename-refactoring stink etc etc.

Granted I'm not all that familiar with the grails source and the
grails/hibernate integration, but I really fail see the downside here. Is
there a hibernate restriction or issue preventing us from doing this?

Best,
Matias




McGSoftware wrote:
>
> Question & comment:
>
> Is there a way for GORM to map to dbms (MySQL) that has native sql enum
> support?
> Using strings for the enum values to/from SQL is much betta for reporting,
> hand sql and ETL ops.
>
> public enum UserStatus {Invalid, Active, Terminated}
>
> class Person {
> ... other properties removed...
> String name
> UserStatus status
>
> static mapping = {
> table 'person2'
> }
> }
>
> For example:
> CREATE TABLE IF NOT EXISTS person (
> ... other fields not shown...
> name varchar(35) UNIQUE NOT NULL
> COMMENT 'The persons name" )',
> status ENUM('Invalid', 'Active', 'Terminated') NOT NULL DEFAULT 'Active'
> COMMENT 'Status of this person from systemic perspective'
> )ENGINE=InnoDB;
>
> The current impl I tried seems to use enum ordinal values, which is has
> proven to be dangerous from a maintenance / production data perspective in
> my experience.
>
> If we *must* map to integer values (which is not preferable for MySQL),
> I'd prefer to force
> the developer to manually set the integer values. Otherwise, a simple enum
> value
> refactoring could eventually cause a nightmare in your production data.
>
> For example, if a developer accidentally reorders enums in the
> declarations, adds a new enum value
> in the middle, etc. Unit tests often show no errors (if new data is
> generated for the test itself), but
> when pushed to production, the new enum int values now get mixed up with
> the old enum int values causing a nasty problem that is very difficult to
> unravel after you finally discover it and users have
> already been creating/updating data.
>
> // Manual enum map. Now you can rename enums, add and remove them
> // without breaking production data - as long as they are unique
> // numbers.
> public enum UserStatus implements EnumMapValue {
> Invalid{ public int dbmsValue() { return 1; }},
> Active { public int dbmsValue() { return 5; }},
> Terminated { public int dbmsValue() { return 10; }};
> }
>
> // Framework enum mapping (optional) for those wanting to avoid the enum
> // ordinal mapping nightmare against production databases. Requires
> // developers to manually assign int value for each enum value.
> public interface EnumMapValue {
> public int dbmsValue();
> }
>
>
>

--
View this message in context: http://www.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p22333629.html
Sent from the grails - user mailing list archive at Nabble.com.


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

http://xircles.codehaus.org/manage_email
Robert Fletcher
2009-03-04 16:38:05 UTC
Permalink
This has already been implemented. See:

http://www.grails.org/1.1-RC1+Release+Notes#Enhanced%20Enum%20Support

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

http://xircles.codehaus.org/manage_email
eas
2009-11-19 17:34:15 UTC
Permalink
Robert,

Please refer to the release notes for 1.1
http://www.grails.org/1.1+Release+Notes

"Enum types can now specify a getId() method that GORM will call to persist
the state of an enum. This an alternative to using either the Enum name or
the ordinal value to persist an enums state"

I have an enum and class defined as follows in 1.1. When I try to create an
instance of the class, the enum name gets stored in the database instead of
the id. So I get OK and FAILED in the database instead of 0/1.
So I was wondering if this feature was really implemented in 1.1 or in a
later version because I see the same note listed under release notes for 1.1
RC1
http://www.grails.org/1.1-RC1+Release+Notes#Enhanced%20Enum%20Support

If this works only with 1.1 RC1, is there a work around for 1.1 where I can
override the hibernate mapping for the enum in the domain class?
I cannot create an enum with a name of 0 or 1 as the name needs to start
with a letter. I'm forced to make this field an enum to get it to work with
the filterpane plugin.


enum RunStatus {

OK('0', 'OK'), FAILED('1','Failed')

RunStatus(String id, String display) {
this.id = id;
this.display = display;
}
final String id
private final String display;
public String getDisplay() { return this.display; }
}

class testenum implements Serializable{

static constraints = {
}

RunStatus runStatus

static mapping={
table "TEST_ENUM"
version false
id generator:"sequence", params:[sequence:"TEST_SEQ"]
columns {
id column: "ID"
runStatus column: "RUN_STATUS"
}
}

}

Thanks,
eas


Robert Fletcher wrote:
>
> This has already been implemented. See:
>
> http://www.grails.org/1.1-RC1+Release+Notes#Enhanced%20Enum%20Support
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
> http://xircles.codehaus.org/manage_email
>
>
>
>

--
View this message in context: http://old.nabble.com/are-new-Enums-in-gorm-safe--tp17699283p26421409.html
Sent from the grails - user mailing list archive at Nabble.com.


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

http://xircles.codehaus.org/manage_email
Loading...