jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: mapping conversion

From: Pinaki Poddar <ppoddar_at_us.ibm.com>
Date: Thu, 12 Jan 2012 10:04:44 -0800

1. On the queries section, it may be worthwhile to mention that the binding
parameters or projected terms referring to a converted attribute are of
type <X> i.e. the type of the attribute.
2. It may be useful to allow static method of a "converter" class be
invoked for conversion. Typical conversion (e.g. boolean to integer) can
then be handled more centrally/uniformly.



Regards --

Pinaki Poddar
Chair, Apache OpenJPA Project http://openjpa.apache.org/
JPA Expert Group Member
Application & Integration Middleware








From: Linda DeMichiel <linda.demichiel_at_oracle.com>
To: jsr338-experts_at_jpa-spec.java.net
Cc: michael keith <michael.keith_at_oracle.com>
Date: 01/11/2012 04:50 PM
Subject: [jsr338-experts] Re: mapping conversion



Are there any additional comments on this proposal?

If so, please post them now.

If not, I will proceed to add this to the spec.

thanks,

-Linda


On 12/19/2011 1:22 PM, Linda DeMichiel wrote:
> Hi all,
>
> It would be good to get some feedback from you on this proposal!
>
> As I hope you might expect, I don't have any major feedback since
> Mike and I have discussed this beforehand :-) when he was kind enough
> to volunteer to drive this feature.
>
> The few suggestions I do have are embedded below. Otherwise, I
> think we should proceed to add this feature to the spec.
>
> thanks,
>
> -Linda
>
>
> On 12/9/2011 1:02 PM, michael keith wrote:
>> Hi everyone,
>>
>> One of the most common feature requests from people who are mapping
entities using JPA is a way to transform or convert
>> the state from the way it is stored in the entity attribute to the way
it is stored in the database, and vice versa. A
>> “converter” provides this functionality. Below is a proposal for
converters.
>>
>> A converter is an object that implements the
javax.persistence.mappings.EntityAttributeConverter interface, defined as:
>>
>> (*** OPEN ISSUE: Should the package just be javax.persistence or should
a subpackage be used in anticipation of other
>> mapping extensions? Some people have asked for a mapping API and this
class would probably fit in with that.)
>>
>
> I would keep this in javax.persistence, as it is pretty basic
functionality.
> We can revisit later on (i.e. until JPA 2.1 PFD) if we change our mind.
>
>> (*** OPEN ISSUE: Is there a better classname and method pair?)
>>
>
> I would drop "Entity" from the interface name
>
>> /**
>> * A class that implements this interface can be used to convert entity
attribute state
>> * into database column representation and back again. Note that the X
and Y types may
>> * be the same Java type.
>> *
>> * @param X The type of the entity attribute
>> * @param Y The type of the database column
>> */
>> |public interface EntityAttributeConverter<X,Y> {||
>> /** ||
>> * Converts the object stored in the entity attribute into the data
representation||
>> || * to be stored in the database.
>> *
>> * @param attributeObject The object in the entity attribute to be ||
converted
>> * @return The converted data to be stored in the database column||
>> */||
>> public Y convertToDatabaseColumn (X attributeObject);||
>> ||
>> /** ||
>> * Converts the data stored in the database column into an object ||
>> * to be stored in the entity attribute.||
>> *||
>> * @param dbData The data from the database column to be converted||
>> * @return The converted state to be stored in the entity attribute||
>> */||
>> public X convertToEntityAttribute (Y dbData);||
>> }
>>
>> |A converter is defined using a javax.persistence.Converter annotation.
It is similar to a TableGenerator and
>> SequenceGenerator in that it can be defined on any entity class, mapped
superclass, or entity attribute, and given a
>> name, but the name must be unique within the scope of the persistence
unit.
>>
>> The annotation to use on the attribute is defined as:
>>
>> |_at_Target({TYPE, METHOD, FIELD})
>> @Retention(RUNTIME)
>> public @interface Converter {
>> String name();
>> Class converterClass();
>> }
>> |
>> In order to make use of a converter the @Convert annotation is used on
an entity or mapped superclass attribute. The
>> @Convert annotation is defined as:
>>
>> |_at_Target({METHOD, FIELD})
>> @Retention(RUNTIME)
>> public @interface Convert {
>> String value();
>> }
>> |
>> It annotates an entity attribute and specifies the name of the
converter. The same converter can be referenced by any
>> number of @Convert annotated attributes.
>> Example:
>>
>> |_at_Entity
>> @Converter(name="booleanToInteger",
>> converterClass=BooleanToIntegerConverter.class)
>> public class Employee {
>> @Id long id;
>> @Convert("booleanToInteger")
>> boolean fullTime;
>> ...
>> }||
>> |
>> |public class BooleanToIntegerConverter implements
EntityAttributeConverter<Boolean,Integer> {
>> public Integer convertToDatabaseColumn (Boolean attributeObject) {
>> return (attributeObject ? 1 : 0);
>> }
>> public Boolean convertToEntityAttribute (Integer dbData) {
>> return (dbData > 0)
>> }
>> }
>>
>
> Since the converter is a class (unlike TableGenerator and
SequenceGenerator),
> I'm thinking it would be nicer if we could apply the annotation to the
> converter class rather than to an entity, mapped superclass, or attribute
> in order to define the class as a converter.
>
> We could then default the name of the converter to the lowercased
> unqualified class name, or allow a name to be specified.
>
> e.g.,
>
> @Converter //name defaults to booleanToInteger
> public class BooleanToInteger implements AttributeConverter {...}
>
> or
> @Converter(name="booleanToInt")
> public class BooleanToInteger implements AttributeConverter {...}
>
>
>
>> |The Container is responsible for invoking the corresponding method when
loading a converted entity attribute from the
>> database, or before saving that entity attribute state to the database.
>>
>> The @Convert annotation may be used on default or explicitly mapped
basic attributes. It is not portably supported to
>> use @Convert on mappings marked with @Enumerated, @Temporal, @Id,
@Version or on embedded, relationship or element
>> collection attributes.
>>
>> (*** OPEN ISSUE: Should we require providers to support some of these
mappings? I can see supporting the conversion of
>> temporal and enumerated attribute types, but in those cases @Convert
would be used on its own, not in combination with
>> either @Enumerated or @Temporal.)
>>
>
> Yes
>
>> Schema Generation
>>
>> When using schema generation a provider may choose to assume the column
type matches the entity attribute type if no
>> additional @Column.columnDefinition is supplied, or a provider may have
an alternate way of deciding the column type for
>> an entity attribute.
>>
>> Queries
>>
>> Instances of attribute values in JP QL or criteria queries (such as in
comparisons or bulk assignments, etc) must be
>> converted to database types before the queries are executed. If the
result of a query includes one or more specific
>> entity attributes then the results must be converted to entity attribute
form before being returned.
>>
>> XML
>>
>> Converters can be defined in XML at method, class, mapping file or
persistence unit level, similar to generators, and
>> will override the same named converters if such converters were defined
in annotation form.
>>
>
> If we follow the suggestion above, I would do this at mapping file or
persistence unit levels only.
>
>> Enhancements
>>
>> This proposal covers converting data from a single column to a single
entity attribute. The assumptions are:
>>
>> a)This will cover the 90% case
>>
>> b)More advanced cases, such as multiple columns to a single attribute,
can be covered by a more advanced mapping or a
>> more advanced converter type that can be added later if necessary
>>
>> c)It is not worth convoluting the simple case to handle a much less
likely complex case
>>
>> Comments?
>>
>> -Mike
>>