I tried with the following annotations: @Persistent @Type( String.class ) @Externalizer( "Shape.typesToString" ) @Factory( "Shape.typesFromString" ) @Column( name="shape_types" )
I also made an attempt without Externalizer and Factory and another one with ElementType instead of Type. In every case, I get the same error message. :( Christian On 7/13/07, Patrick Linskey <[EMAIL PROTECTED]> wrote:
Hmm. You may also need to specify the type of the externalized value for the field; I thought that this happened automatically. Try specifying @Type(String.class) on the field as well. -Patrick On 7/13/07, Christian Defoy <[EMAIL PROTECTED]> wrote: > Hi Patrick, > > Thanks for the answer. You guess correctly when you say that I want a > stringified version of my EnumSet. :) > > I tried to simply mark it @Persistent instead of @PersistentCollection > but I got a different error message: > > org.apache.openjpa.util.MetaDataException: The type of field > "Shape.types" isn't supported by declared persistence strategy > "Persistent". Please choose a different strategy. > at org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parsePersistent(AnnotationPersistenceMetaDataParser.java:1351) > at org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parseMemberAnnotations(AnnotationPersistenceMetaDataParser.java:952) > at org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parseClassAnnotations(AnnotationPersistenceMetaDataParser.java:599) > at org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parse(AnnotationPersistenceMetaDataParser.java:349) > at org.apache.openjpa.persistence.PersistenceMetaDataFactory.load(PersistenceMetaDataFactory.java:227) > at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:421) > at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:277) > at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:221) > at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:194) > at org.apache.openjpa.enhance.PCClassFileTransformer.transform(PCClassFileTransformer.java:127) > at sun.instrument.TransformerManager.transform(TransformerManager.java:122) > at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:155) > at java.lang.ClassLoader.defineClass1(Native Method) > at java.lang.ClassLoader.defineClass(ClassLoader.java:620) > at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) > at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) > at java.net.URLClassLoader.access$100(URLClassLoader.java:56) > at java.net.URLClassLoader$1.run(URLClassLoader.java:195) > at java.security.AccessController.doPrivileged(Native Method) > at java.net.URLClassLoader.findClass(URLClassLoader.java:188) > at java.lang.ClassLoader.loadClass(ClassLoader.java:306) > at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) > at java.lang.ClassLoader.loadClass(ClassLoader.java:251) > at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) > at java.lang.Class.forName0(Native Method) > at java.lang.Class.forName(Class.java:242) > at org.apache.openjpa.meta.MetaDataRepository.classForName(MetaDataRepository.java:1234) > at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1222) > at org.apache.openjpa.kernel.AbstractBrokerFactory.loadPersistentTypes(AbstractBrokerFactory.java:240) > at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:192) > at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:142) > at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:190) > at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:143) > at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:55) > at ShapeHelper.main(ShapeHelper.java:21) > > Could it be that I need to specify something in my persistence.xml or > put annotations in my enum? I tried a few variations but without > success... > > Christian > > On 7/13/07, Patrick Linskey <[EMAIL PROTECTED]> wrote: > > 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 <[EMAIL PROTECTED]> 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 > > > -- Patrick Linskey 202 669 5907
