An entirely different twist / solution to this problem could be to provide a customizable post processing step to transform the results returned by a query.
This could be considered an orthogonal feature though.
//JPA 2 API
interface ResultTransformer {
public Object transformTuple(Object[] tuple, String[] aliasOrColumnName);
}
//user implementation
class ConstructorResultTransformer {
private final Constructor constructor;
public ConstructorResultTransformer(Constructor constructor) {
this.constructor = constructor;
}
public Object transformTuple(Object[] tuple, String[] aliasesOrColumnNames) {
//TODO try catch for *Exception
return constructor.newInstance( tuple );
}
}
This is not limited to constructors, one can think of many use cases like:
- returning maps
- setting values based on setters rather than constructors
This is not a fleshed out proposal, a few areas need to be worked out, including:
- how is aliasesOrColumnNames exactly defined
- how to make it so it plays well in the type system of a TypedQuery
Emmanuel
On 14 avr. 2011, at 02:16, Linda DeMichiel wrote:
> Another pending item in the query area is the ability to use
> constructors for non-entity results of native queries.
>
> Here's another strawman proposal to get the discussion started:
>
>
> To support the use of constructors in SqlResultSetMapping, we could
> define a ConstructorResult mapping:
>
> @Target(value={})
> @Retention(value=RUNTIME)
> public @interface ConstructorResult {
> Class targetClass();
> ColumnResult columns();
> }
>
>
> This could be used in combination with @EntityResult and @ColumnResult
> in SQLResultSetMapping:
>
> @Target({TYPE})
> @Retention(RUNTIME)
> public @interface SqlResultSetMapping {
>
> /**
> * The name given to the result set mapping, and used to refer
> * to it in the methods of the Query API.
> */
> String name();
>
> /** Specifies the result set mapping to entities. */
> EntityResult[] entities() default {};
>
> /** Specifies the result set mapping to constructors. */
> ConstructorResult[] classes() default {};
>
> /** Specifies the result set mapping to scalar values. */
> ColumnResult[] columns() default {};
> }
>
>
> We should also be more specific about the relationship among the
> shape of the SELECT list, the specified SqlResultSetMapping, and the
> order in which results are returned by the execution of the query.
> This is currently undefined in the spec.
>
> For example:
>
> When a SqlResultSetMapping specifies more than one mapping type (i.e.,
> more than one of EntityResult, ConstructorResult, ColumnResult), then
> for each row in the SQL result, the query execution will result in an
> Object[] whose elements are as follows, in order: any entity results
> (in the order in which they are defined in the entities element); any
> instances of classes corresponding to constructor results (in the
> order defined in the classes element); and any instances corresponding
> to column results (in the order defined in the columns element).
>
> Another issue is that when a column is not mapped as an entity
> attribute, there is currently no way to specify the type to be returned
> by the query (e.g., Timestamp instead of Date).
>
> I suggest that we address this by adding another element to
> @ColumnResult, e.g., type, which would default to void.class for
> default JDBC type mapping.
>
>
> Feedback, please!
>
> thanks,
>
> -Linda
>