openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ryan Fogarty <rfoga...@adaptivemethods.com>
Subject Re: Is JPA 2 going to have something like JAXBs @XmlJavaTypeAdapter ?
Date Mon, 30 Mar 2009 16:54:14 GMT
Hi Jeremy,

   I really appreciate your response; it's good to know there is a 
workaround for OpenJPA (as I understand it, Hibernate can also do this 
as part of its proprietary interface). I just sent an 11th hour comment 
to the JSR317 committee (jsr-317-comments@jcp.org) regarding the issue. 
Below is a copy of that email. I suspect that my solution is overly 
simplified but might get the experts thinking about a proper solution.

Thanks again for your response,
Ryan

-- email to jsr 317:

Dear JSR 317 committee,

    JAXB has a simple and powerful annotation type @XmlJavaTypeAdapter 
that provides an adapter class to convert some opaque class type to 
something that is more easily JAXB annotated to marshall/unmarshall 
to/from XML.

   Seems like a massive oversight of the JPA spec. For instance, I 
cannot do the simplest thing such as make JPA embed a UUID as a varchar 
in a table, instead it insists on serializing to byte[].

I would propose that 2 annotations are created one for an Entity adapter 
and another for an Embeddable.

public @interface EntityAdapter {
    Class<? extends PersistentTypeAdapter> value();
}

public @interface EmbeddedAdapter {
    Class<? extends PersistentTypeAdapter> value();
}

public interface PersistentTypeAdapter<PersistentType,BoundType> {

    PersistentType marshall(BoundType v);
    BoundType unmarshall(PersistentType v);
}


Example Usage:

@Entity
public class Foo {
   //...

   public static class UuidAsVarchar implements 
PersistentTypeAdapter<String,UUID> {
      public String marshall(UUID v) { return v != null ? v.toString() : 
null; }
      public UUID unmarshall(String v) { return v != null ? 
UUID.fromString(v) : null; }
   }

   @EmbeddedAdapter(UuidAsVarchar.class)
   private UUID uid;

   //...
}

Please extrapolate on @EntityAdapter usage. Obviously it would adapt to 
a class marked as @Entity.


Jeremy Bauer wrote:
> Ryan,
>
> I agree, this would be a useful feature to have standardized by the 
> JPA specification.  My guess is that it would be too late to try to 
> get something into JPA 2.0, but one could recommend this feature for 
> inclusion in a future version of the spec.  Pinaki and Kevin (cc'd) 
> participate in the expert group so they may have recommendations for 
> submitting feature requests.
>
> Currently, you can do the conversion yourself within your business 
> logic (or create separate entities or embeddables for the mappings), 
> which can result in an indirect and sometimes quirky OR mapping..  or 
> you can use OpenJPA's @Strategy extension to specify a custom value 
> mapping handler. Here is an example handler for UUID:
>
> package strat;
>
> import java.util.UUID;
>
> import org.apache.openjpa.jdbc.kernel.JDBCStore;
> import org.apache.openjpa.jdbc.meta.ValueMapping;
> import org.apache.openjpa.jdbc.meta.strats.AbstractValueHandler;
> import org.apache.openjpa.jdbc.schema.Column;
> import org.apache.openjpa.jdbc.schema.ColumnIO;
> import org.apache.openjpa.meta.JavaTypes;
>
> public class UUIDValueHandler extends AbstractValueHandler {
>
>     public Column[] map(ValueMapping vm, String name, ColumnIO io,
>         boolean adapt) {
>         Column col = new Column();
>         col.setName(name);
>         col.setJavaType(JavaTypes.STRING);
>         return new Column[]{ col };
>     }
>    
>     public boolean isVersionable() {
>         return true;
>     }
>    
>     /**
>      * Convert the object value to its datastore equivalent.
>      */
>     public Object toDataStoreValue(ValueMapping vm, Object val,
>         JDBCStore store) {
>         if (val == null)
>             return null;
>
>         UUID uuid = (UUID) val;
>         return uuid.toString();
>     }
>
>     /**
>      *  Convert the datastore value to its object equivalent.
>      */
>     public Object toObjectValue(ValueMapping vm, Object val) {
>         if (val == null)
>             return null;
>
>         String uuidStr = (String)val;       
>         return UUID.fromString(uuidStr);
>     }
> }
>
> @Entity
> public class EntityA {
> ...   
>     @Strategy("strat.UUIDValueHandler")
>     private UUID uuid;
> ...
> }
>
> Using this custom value handler, UUID will be mapped internally 
> to/from a string type. In addition, the schema factory (if used) will 
> create the appropriate database column type(s).  The OpenJPA unit test 
> suite has an additional example usage of @Strategy which maps an 
> object to/from multiple database columns.  Search for @Strategy in 
> org.apache.openjpa.persistence.jdbc.annotations.NonstandardMappingEntity.
>
> hth,
> -Jeremy
>
>
> On Mon, Mar 30, 2009 at 9:28 AM, Ryan Fogarty 
> <rfogarty@adaptivemethods.com <mailto:rfogarty@adaptivemethods.com>> 
> wrote:
>
>     I use @XmlJavaTypeAdapter a lot to manipulate our data model for
>     classes
>     that just don't naturally fit into an XML model (like custom
>     containers
>     and the sort). Seems to be one of the most intuitive and powerful
>     tools
>     in JAXBs toolbox but I can't find anything like it in JPA 1 or 2.
>
>     For instance, I can't seem to do the simplest thing with JPA such as
>     take a java.util.UUID and have OpenJPA map it into a STRING.
>
>     It looks like there is no chance of getting this into JPA 2 since they
>     are in final draft. I just can't imagine such a useful tool *not*
>     existing in a powerful API like JPA, so what gives? Have I missed
>     something fundamental?
>
>     Thank you,
>     Ryan
>
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message