openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Patrick Linskey" <plins...@gmail.com>
Subject Re: Persistence of EnumSet
Date Fri, 13 Jul 2007 17:49:30 GMT
Hi,

Externalizers and factories apply to the entire instance, not to the
innards of the collection. I think that you've got things in a bit of
a hybrid state right now.

First, the problem is happening because EnumSet is an abstract type.
The only way to get EnumSet instances is by using the static methods
in the EnumSet class. Sadly, this is in stark contrast to the
contracts outlined in the Javadoc for java.util.Collection, and
OpenJPA requires compliance with some of those contracts. Put more
simply, OpenJPA does not natively support EnumSet at this time. IMO,
it would be worthwhile to add support for EnumSet (and EnumMap) at
some point. However, this might be difficult / limiting due to the
lack of extensibility of the EnumSet type and its subtypes.

So, in terms of a solution: how do you want this data to be mapped to
the database? Are you looking to have a single column in a table that
contains the Stringified representation of the EnumSet, or are you
looking to have a join table with rows for each Stringified enum value
in the set? Given the method names in your externalizer and factory,
I'm going to assume the former.

In this case, the field is not really a persistent collection from
OpenJPA's standpoint. You'll want to just mark it as @Persistent
instead of @PersistentCollection. Once you've done this, one of two
things will happen:

1. you will still get the second-class object problem

or 2. it will work without an exception, but changes you make to the
collection will not be noticed. If you set the field to a new value,
the change will be detected, but mutations to the data structure
itself will not. Currently, there is no way around this -- you'll need
to explicitly dirty the field (OpenJPAEntityManager.dirty(o,
"nameOfEnumSetField")) when you mutate the record.


If you run into the first case, we'll need to change OpenJPA to allow
bypassing of proxy logic somehow.

Also, we should probably allow field-by-field enabling of a
more-expensive dirty checking strategy so that you don't need to
manually mark the field as dirty.

-Patrick

On 7/13/07, Christian Defoy <christian.defoy@gmail.com> wrote:
> Hello!
>
> Is there a way to persist an EnumSet easily with OpenJPA?  I tried
> with an externalizer:
>
>     @PersistentCollection
>     @Externalizer( "test.Shape.typesToString" )
>     @Factory( "test.Shape.typesFromString" )
>     @ElementType( String.class )
>     @Column( name="shape_types" )
>     private EnumSet<ShapeTypes> types;
>
> When I try to run this, I get the following error message, which makes
> me believe I am doing something wrong...
>
> Caused by: <0.9.7-incubating fatal general error>
> org.apache.openjpa.persistence.PersistenceException: Unable to create
> a second class object proxy for abstract type "class
> java.util.EnumSet".  You must use a concrete type or a recognized
> interface.
>         at org.apache.openjpa.util.ProxyManagerImpl.toProxyableCollectionType(ProxyManagerImpl.java:320)
>         at org.apache.openjpa.util.ProxyManagerImpl.newCollectionProxy(ProxyManagerImpl.java:191)
>         at org.apache.openjpa.kernel.StateManagerImpl.newFieldProxy(StateManagerImpl.java:1571)
>         at org.apache.openjpa.kernel.SingleFieldManager.proxy(SingleFieldManager.java:104)
>         at org.apache.openjpa.kernel.StateManagerImpl.proxyFields(StateManagerImpl.java:2624)
>         at org.apache.openjpa.kernel.PNonTransState.initialize(PNonTransState.java:44)
>         at org.apache.openjpa.kernel.StateManagerImpl.setPCState(StateManagerImpl.java:213)
>         at org.apache.openjpa.kernel.StateManagerImpl.commit(StateManagerImpl.java:919)
>         at org.apache.openjpa.kernel.BrokerImpl.endTransaction(BrokerImpl.java:2194)
>         ... 8 more
>
> Thanks in advance!
>
> Christian
>


-- 
Patrick Linskey
202 669 5907

Mime
View raw message