jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: mapping conversion

From: michael keith <michael.keith_at_oracle.com>
Date: Tue, 17 Jan 2012 09:31:11 -0500

There was apparently a typo in the example in my earlier message. The
@Convert annotation should have been
...
@Convert(com.acme.BooleanToInteger*Converter*.class)
boolean fullTime;
...

-Mike

On 16/01/2012 4:31 PM, michael keith wrote:
> I am fine with annotating the converter class instead of adding the
> @Converter annotation to the entity class, although I don't see that
> there are too many use cases for needing to define the target
> convertable class name. The type parameter of the converter will
> define the one that it is intended to convert, and for the most part
> will be enough. Two cases that I can think of that *might* warrant an
> additional type parameter are:
> a) You want to map both the primitive and wrapper types (e.g. boolean
> and Boolean). Not sure how often this would occur in practice.
> b) You want to convert a class and all its subclasses. A subclass
> might actually have additional state, though, so the conversion might
> not be sufficient.
>
> I don't believe (a) is all that useful, really. It is probably
> reasonable for people to either add another converter for the
> primitive type or put a @Convert annotation on it.
>
> Similarly for (b), an empty converter subclass could be added to
> handle each convertible type subclass.
>
> I was also thinking that string names for the converters are shorter
> but less typesafe than just using the class name of the converter.
>
> Example:
>
> @Converter
> public class BooleanToIntegerConverter implements
> AttributeConverter<Boolean, Integer> { ... }
> @Converter(autoApply=true)
> public class EmployeeDateConverter implements
> AttributeConverter<com.acme.EmployeeDate, java.sql.Date> { ... }
>
> @Entity
> public class Employee {
> @Id long id;
> @Convert(com.acme.BooleanToInteger.class)
> boolean fullTime;
> ...
> // Automatically applied
> EmployeeDate startDate;
> }
>
> On 16/01/2012 12:05 AM, Bernd Müller wrote:
>> Hi,
>>
>> I would advocate for Lindas proposal, giving some additional
>> unique/global/local arguments
>>
>> Am 12.01.2012 01:49, schrieb Linda DeMichiel:
>>> 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
>>>
>> I see a problem: the name of the converter is unique in the pu but
>> the usage mimics locality for an entity.
>>
>> In JSF there is also a converter annotation called FacesConverter
>> doing similar things. However it is used to annotate the converter (as
>> the name implies ?)
>>
>> The refactored example:
>>
>> @Converter("booleanToInteger")
>> public class BooleanToIntegerConverter implements
>> ...
>> }
>>
>> @Entity
>> public class Employee {
>> @Id long id;
>> @Convert("booleanToInteger")
>> boolean fullTime;
>> ...
>> }
>>
>> The Converter annotation uses "value" instead of "name" and is therefore
>> a little bit less verbose.
>> And the usage of "booleanToInteger" reflects its uniqueness instead
>> of doubling the string literal in one single entity class.
>>
>> To demand for global application of the converter there is a second
>> attribute "forClass" in @Converter defining the Class to apply for.
>>
>> Example
>>
>> @Converter(forClass=SomeBusinessPropertyType.class)
>> public class ConverterForSomeBusinessPropertyType {
>> ...
>> }
>>
>> @Entity
>> public class Employee {
>> ...
>> SomeBusinessPropertyType sbpt; // Converter applied automatically
>> ...
>> }
>>
>>
>> regards
>>
>> Bernd
>>
>>
>>>>> |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)
>>>>> }
>>>>> }
>>>>>
>