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.)
(*** OPEN ISSUE: Is there a better classname and method pair?)
/**
* 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)
}
}
|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.)
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.
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