[hibernate-dev] Mapping JPA's @MapKeyEnumerated and @Enumerated on native-enum supporting datastores
Steve Ebersole
steve at hibernate.org
Fri Aug 26 09:59:33 EDT 2016
I doubt we'd see JPA EnumType expanded, but it never hurts to propose
something.
I did some digging and of the major dbs it seems that only PGSQL supports
enums as a proper data type. The difficulty is handling these through
JDBC. Just do a web search for "pgsql enum jdbc" and you'll find all the
gory details. Basically handling values of that native enum type via JDBC
requires "something extra". The specific "something extra"s I have found
suggested include:
- use of PGSQL-specific classes (PGObject) to handle the conversion
- injection of CASTs in the SQL whereever the enum is used (passing the
value as String from the Java side).
- The use of setObject to pass the enum name (again passing the value as
String from the Java side) rather than setString. Supposedly there is some
JDBC setting that allows setString to work to bind to a db enum column.
I also wonder whether a registered UDT could help here? We could possibly
register a UDT to handle the conversion between the Java enum and the PG
enum. In theory this should allow us to directly handle value using the
Java enum when binding to a PS and reading from a RS. I have not tried,
this is just a hypothesis.
MySQL (and its variants) do have an enum data type, although it is hardly a
"native solution"; in fact it is little more than a VARCHAR data type with
check-constraints. In fact, it is often suggested to *not* use MySQL's
enum support[1].
Bottom line, I am not sure this is reasonable for JPA as far as its real
purpose... ORM. Only one of the major db products (PGSQL) really support
enums natively, and even there handling values of that native enum type via
JDBC is fugly.
[1] https://www.google.com/search?q=mysql+enums+are+evil
On Fri, Aug 26, 2016 at 7:49 AM Sanne Grinovero <sanne at hibernate.org> wrote:
> On 26 August 2016 at 12:51, Steve Ebersole <steve at hibernate.org> wrote:
> > PGSQL has some enum support I know. The problem has always been that
> they
> > are mapped to "special" type codes (think java.sql.Types) which makes it
> > difficult to work with in ORM.
>
> That's very interesting. So in an ideal world, could we propose for
> JPA 2.2 to add a new option to the enum type?
> This could be "NATIVE", or maybe even better "AUTO".
>
> Thanks,
> Sanne
>
>
> > On Fri, Aug 26, 2016 at 6:18 AM Gunnar Morling <gunnar at hibernate.org>
> wrote:
> >>
> >> > I guess we could, but it's sad that we'd still have to default to the
> >> > "wrong" mapping,
> >> > at least for all those people who won't read all of our docs.
> >>
> >> The default for our custom @Enumerated could be NATIVE, but I agree
> people
> >> need to know about that instead of the JPA one.
> >>
> >> > Would that live in OGM or ORM ?
> >>
> >> Good question, depends on whether there is any RDBMS with native enum
> >> support?
> >>
> >>
> >> 2016-08-26 13:02 GMT+02:00 Sanne Grinovero <sanne at hibernate.org>:
> >>
> >> > On 26 August 2016 at 10:34, Gunnar Morling <gunnar at hibernate.org>
> wrote:
> >> > > How about having a custom @Enumerated annotation which offers NATIVE
> >> > > as
> >> > an
> >> > > additional choice?
> >> >
> >> > I guess we could, but it's sad that we'd still have to default to the
> >> > "wrong" mapping,
> >> > at least for all those people who won't read all of our docs.
> >> >
> >> > Would that live in OGM or ORM ?
> >> >
> >> > >
> >> > > 2016-08-26 10:16 GMT+02:00 Emmanuel Bernard <emmanuel at hibernate.org
> >:
> >> > >>
> >> > >> Can you give HotRod's example of native enum - I imagine Protobuf ?
> >> >
> >> > From the OGM testsuite:
> >> >
> >> > @Entity
> >> > public class Bookmark {
> >> >
> >> > public enum Classifier {
> >> > HOME, WORK
> >> > }
> >> >
> >> > @Id
> >> > private String id;
> >> > @Enumerated(EnumType.STRING)
> >> > private Classifier classifier;
> >> > [...]
> >> > }
> >> >
> >> > Is mapped as:
> >> >
> >> > message Bookmark {
> >> > required string id = 1;
> >> > optional string classifier = 2;
> >> > [...]
> >> >
> >> > (correctly as it's explicitly requesting a STRING EnumType)
> >> >
> >> > A more "native" Protobuf mapping would look like:
> >> >
> >> > enum Classifier {
> >> > HOME = 0;
> >> > WORK = 1;
> >> > }
> >> >
> >> > message Bookmark {
> >> > required string id = 1;
> >> > optional Classifier classifier = 2;
> >> > [...]
> >> >
> >> > I had already implemented this, just realising later that there's no
> >> > way to enable this better looking mapping.
> >> >
> >> > >>
> >> > >> The issue I see is that ordinal could be an acceptable explicit
> >> > >> decision
> >> > >> that would not be available to the user if you use default as
> native.
> >> > >>
> >> > >> I'm tempted to go native all the time at the detriment of people
> that
> >> > >> need high customization.
> >> >
> >> > I'd be tempted too as the second mapping looks much more natural,
> >> > however this would break things for people who need it to be an
> >> > integer, e.g. if they have other clients who expect an int.
> >> > On the other hand, the "I need compatibility with another client"
> >> > argument is quite weak, as at this stage the Hot Rod Dialect generates
> >> > its own schema and pretty much mandates using the one it generates.
> >> >
> >> > Proposal: I have it mapped as "native enums" by default, and give a
> >> > global configuration property to honour the annotations instead? This
> >> > would be a global setting though, so if one wants one attribute
> >> > "native encoded" and another "int encoded" that wouldn't be possible.
> >> >
> >> > Thanks,
> >> > Sanne
> >> >
> >> > >>
> >> > >> Emmanuel
> >> > >>
> >> > >> On Mon 2016-08-15 18:14, Sanne Grinovero wrote:
> >> > >> > In the context of Hibernate OGM, it turns out that some
> datastores
> >> > >> > have a rather nice "native" support for enums.
> >> > >> >
> >> > >> > We aim to map each property of the user's domain model to its
> most
> >> > >> > appropriate "physical type", unless the choice is overriden by
> the
> >> > >> > an
> >> > >> > explicit user request.
> >> > >> >
> >> > >> > In the case of an Enum, JPA annotations such as @Enumerated have
> an
> >> > >> > attribute EnumType to choose the physical representation:
> >> > >> >
> >> > >> > public enum EnumType {
> >> > >> > /** Persist enumerated type property or field as an integer.
> */
> >> > >> > ORDINAL,
> >> > >> >
> >> > >> > /** Persist enumerated type property or field as a string. */
> >> > >> > STRING
> >> > >> > }
> >> > >> >
> >> > >> > However, there's no support for a "NATIVE". Also, the annotation
> >> > >> > specifies that "ORDINAL" is the default value so I can't just
> >> > >> > assume
> >> > >> > that the user didn't specify anything and we're good to use our
> own
> >> > >> > NATIVE implementation.
> >> > >> >
> >> > >> > Assuming that we can't change the JPA spec, any suggestion on
> when
> >> > >> > I
> >> > >> > could have the Hot Rod dialect for OGM to actually produce a
> "nice"
> >> > >> > mapping into native enums?
> >> > >> >
> >> > >> > I'm tempted to just use natives all the time; In the case in
> which
> >> > >> > the
> >> > >> > user opted for "STRING" I could drop a warning - or decide to
> >> > >> > honour
> >> > >> > that - but in case of ORDINAL I just can't tell if it's a default
> >> > >> > choice or not so I think a warning would be too much.
> >> > >> >
> >> > >> > Another alternative would be that I "go native" when the
> >> > >> > @Enumerated
> >> > >> > annotation isn't specified at all: looks like this mapping is
> valid
> >> > >> > according to ORM as it seems to treat it as if there was an
> >> > >> > implicit
> >> > >> > @Enumerated annotation; I'm not happy about having to rely on
> >> > >> > people
> >> > >> > to not use an explicit annotation though.
> >> > >> >
> >> > >> > Thanks,
> >> > >> > Sanne
> >> > >> > _______________________________________________
> >> > >> > hibernate-dev mailing list
> >> > >> > hibernate-dev at lists.jboss.org
> >> > >> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >> > >> _______________________________________________
> >> > >> hibernate-dev mailing list
> >> > >> hibernate-dev at lists.jboss.org
> >> > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >> > >
> >> > >
> >> >
> >> _______________________________________________
> >> hibernate-dev mailing list
> >> hibernate-dev at lists.jboss.org
> >> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
More information about the hibernate-dev
mailing list