openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jan Dockx <jando...@gmail.com>
Subject Suggestion: @Column with ValueHandlers that use multiple columns
Date Thu, 30 Oct 2008 15:34:06 GMT
We suggest a change in how OpenJPA determines the names to be used for  
DB columns when using value handlers that use multiple columns. When a  
@Column annotation (or the equivalent in XML) is found for a property  
or field that is handled by a value handler, the name passed to the  
map() method should be the name in the annotation, and not the name of  
the property or field.




While working with ValueHandlers that use multiple columns, we found  
the following behavior (using OpenJPA on WebSphere 6.1..., thus  
OpenJPA 1.0.3. (?)):

For a developer of an entity that uses the complex value type for  
which we write the value handler, the complex value type is "one  
thing". She doesn't (want to) know the internal complexity. The goal  
of complex value types is indeed encapsulation. The developer of the  
entity also does not (want to) know on how many and which columns we  
want to persist.

The name given as parameter in the map() function of a ValueHandler is  
the name of the underlying property / field.
It is the intention to define names on the Columns we return that are  
distinct for the different columns, in the context of any use (i.e.,  
for many different properties that use our complex value type, in many  
different entities, by many different developers). Therefor it is not  
a bad idea to name the columns something like <code>name +  
"_subcolumndescription"</code>.

E.g., we have a TimeInterval complex value type, that features a begin  
and end property. We want, in particular circumstance, to persist time  
intervals in 2 TIMESTAMP columns, called <code>name + "_begin"</code>  
and <code>name + "_end"</code>. When applied to a property / field  
called "subscriptionPeriod", you thus get in the database the columns  
"SUBSCRIPTIONPERIOD_BEGIN" and "SUBSCRIPTIONPERIOD_END".

So far, so good.

Now, for several good reasons, developers might want to override the  
(base) name used for column names. We don't want to use the name of  
the field / property, but something else (particularly handy when your  
style uses a prefix for instance variables like "$" or "_"). This is  
supported in JPA with the @Column() annotation.

Now, we observe that when we combine this annotation with the OpenJPA  
value handlers, that we get an error, because we have only defined 1  
column name, and we need n for our property. The solution is to use  
the OpenJPA @Columns({}) annotation, where we can nest a @Column()  
annotation with a specific name for each column.

In our example, suppose we want to use "SUBSRC" as column name:

@Column("SUBSCR") gives an error

and

@Columns({@Column("SUBSCR_BEGIN"), @Column("SUBSCR_END")}) gives  
indeed 2 columns with those names in the database. The naming is then  
dependent on the order.

We suggest that this breaks encapsulation. To make this work, the  
developer indeed needs to be aware of the internal of  
TimeIntervalValueHandler.





We suggest a small change in OpenJPA: when calling the map() method,  
give as name the name of the property / field if no @Column()  
annotation is found, or if the @Columns() annotation is found  
(although then it is irrelevant, but passing null is not a backward  
compatible option). This is the current behavior. In the case the  
@Column() annotation (or the equivalent in XML) is found however, pass  
in the name given in the annotation as name parameter to the map()  
method, instead of the current property / field name. Also, the  
verification would have to be changed to not throw an error in this  
case.





The behavior with @Columns() should be kept as fallback for legacy  
databases (although in that case you probably will not be working with  
complex value types and value handlers?).






Mime
View raw message