Thanks, Oliver.
See comments below.
On 12/01/2012 3:30 AM, Oliver Gierke wrote:
> Hi all,
>
> comments inline…
>
> Am 12.01.2012 um 01:49 schrieb Linda DeMichiel:
>
>>>> 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.
> Why shouldn't it be allowed for embeddables?
There is nothing stopping someone from using it on mappings *within* an
embeddable, but an embeddable as a whole entails a number of mapped
fields and we are not supporting multiple columns in this round.
>>>> 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.
> Does this mean the converters would be instantiated by the persistence provider then? This would expose it to the same drawbacks EntityListeners currently face: injecting objects into them is quite complicated.
Yes, they would be similar to EntityListeners in the fact that they
would be instantiated by the provider. Injection is not as useful,
though, since the point of converters is simply to transform attribute
state from one form to another, not to perform domain operations. That
doesn't mean we can't allow it, it's just not a priority IMO.
> Is there some notion of a "global converter"? Given Mike's examples one would have to annotate each and every boolean attribute in entity classes with @Convert("booleanToInteger") to get it converted. What if the converters registered would be applied globally to all attributes of the appropriate type (discoverable from generics) and could be explicitly overridden at the field level. Alternatively we could have a "global" flag in the @Converter annotation that triggers this behavior.
The application of a converter to all of the mappings in a persistence
unit is definitely useful and although I originally thought, just to
simplify things, that it would be something for providers to implement,
I tend to agree that it would be better to add standard support for that
now as part of this feature.
A deluxe version would be to define a scope in which the converter
applies: only when specified in @Convert, for all of the attributes in a
class or group of classes, or for the entire persistence unit. That is
probably not necessary, though. I would just add a flag to the
@Converter annotation to declare that it should be applied globally in
the persistence unit. It would also be valuable to add an API method to
the EMF to allow dynamic setting of a default converter so that one
might be able to decide at runtime which converter to use everywhere.
The updated Converter might be:
|_at_Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface Converter {
String name();
Class converterClass();
boolean autoApply() default false;
}|
The EntityManagerFactory API method might be something like:
|void <X,Y> autoApplyMappingConverter(EntityAttributeConverter<X,Y>,
converterClass)
|
meaning that all mappings of exactly class X (primitives and wrappers
are differentiated, as are subclasses from superclasses) would get
automatically converted using this converter.
When a @Convert(converterClass=...) occurs it would always override any
global auto applied converter in effect. To override a global converter
without having to specify a replacement converter, there are a couple of
options:
a) Specify @Convert without a converterclass
b) Specify a separate annotation, e.g. @DontConvert,
@DisableAutoApplyConverter, ...