Nice! Yeah, I remember we discussed such an explicit mapping, which addresses 
the POJO mapping case as is. 

So now I am thinking whether we can make it even more transparent - automap 
property names to column names and JDBC types to Java types. So users won't 
need "Constructor(Object[])", and generally would not concern themselves with 
the ordering of properties in the array (mapping by name instead of position).

Andrus


> On Jul 15, 2022, at 5:37 AM, Nikita Timofeev <ntimof...@objectstyle.com> 
> wrote:
> 
> We already have map(Function) method available in both ColumnSelect
> and SQLSelect that allows to map result from Object[] to anything via
> provided function.
> Here is an example from tests [1]:
> 
> List<ArtistDataWrapper> result = SQLSelect.columnQuery("SELECT * FROM
> ARTIST_CT",
>      Integer.class, String.class, LocalDateTime.class)
>      .map(ArtistDataWrapper::new)
>      .select(context);
> 
> And I experimented with simple PojoMapper that does almost exactly
> what you are suggesting. Not sure if it's available though.
> 
> [1] 
> https://github.com/apache/cayenne/blob/336f0e5297fe6ccdc3b1904ab4f6ee2c6d1ab9dc/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java#L273
> 
> On Thu, Jul 14, 2022 at 10:52 PM Andrus Adamchik <aadamc...@gmail.com> wrote:
>> 
>> Java 17 "records" create some interesting possibilities as quick DTOs. 
>> Mapping complex SQL is still rather painful in Cayenne. You'd get an 
>> Object[] as a result and/or need complex scripting within SQL. I think 
>> records and some API tweaks can help:
>> 
>> 1. SQL result mapping.
>> 
>> record MyRecord(String lastName, String firstName) {} // non-persistent, not 
>> in DataMap
>> 
>> SQLSelect.query("select * from x")
>> 
>>  // new API analogous to "#result" directive but simpler to use
>>  // also we can implement some implicit name conversions ("AB_C" -> "abC")
>>  .resultColumn(0, "firstName")
>>  .resultColumn("LAST_NAME", "lastName")
>> 
>>  // new API - auto-mapping the result to a POJO (record in this case)
>>  .selectAs(MyRecord.class, context);
>> 
>> 
>> 2. Entity result mapping (e.g. a replacement of column and data row queries).
>> 
>> class MyEntity extends _MyEntity {} // Persistent
>> record MyEntityDTO(..) {}  // non-persistent, not in DataMap
>> 
>> List<MyEntityDTO> result = ObjectSelect(MyEntity.class)
>>  .where(MyEntity.NAME.like("Joe"))
>>  .prefetch(MyEntity.ANOTHER.joint())
>> 
>>  // new API - auto-mapping the result to a POJO (record in this case)
>>  .selectAs(MyEntityDTO.class, context);
>> 
>> It will be faster than fetching MyEntity (without ObjectContext 
>> registration, uniquing, merging), and will be a good replacement of column 
>> queries API, requiring no explicit column declarations, and producing a 
>> specific type instead of Object[]. Prefetches can be auto-mapped to record 
>> hierarchies.
>> 
>> Both examples would work with either records or regular POJOs, it is just 
>> that record definitions are so easy to create on the spot, that they can be 
>> used in a multitude of very narrow contexts.
>> 
>> Andrus
>> 
> 
> 
> -- 
> Best regards,
> Nikita Timofeev

Reply via email to