Hi Lukas,

first thanks for the quick responses. 

I tried implementing the provider and recordmappers, but i got a bit stock 
by now.
what i have currently:


public class MyRecordMapperProvider implements RecordMapperProvider {

@Override
public <R extends Record, E> RecordMapper<R, E> provide(RecordType<R> 
recordType, Class<? extends E> type) {
if (type == Account.class) {
return (RecordMapper<R, E>) getAccountRecordMapper();
}
return new DefaultRecordMapper(recordType, type);
}

public static RecordMapper<TAccountRecord, Account> 
getAccountRecordMapper() {
return new RecordMapper<TAccountRecord, Account>() {
@Override
public Account map(TAccountRecord record) {
Account c = new Account();
c.setId(record.getId());
c.setName(record.getName());
c.setCreateTime(record.getCreatetime());
return c;
}
};
}
}

@Test
public void myTest(){
        TAccount a = new TAccount();
List<Account> accountList = 
create.select(a.fields()).from(a).fetch().map(CockpitRecordMapperProvider.getAccountRecordMapper());
}


where the query part doesn´t let me use the recordmapper like this. I guess 
i have to use intoGroups() instead, but even that does not let me use the 
RecordMapper. Maybe because of generics.
Eclipse is whining:

The method map(RecordMapper<? super Record,E>) in the type Result<Record> 
is not applicable for the arguments (RecordMapper<TAccountRecord,Account>)



so i´m curios what would be the correct query for the account class!

also, as i configured jooq within my spring.xml with:


<!--  jooq -->
 <!-- Configure jOOQ's ConnectionProvider to use Spring's 
TransactionAwareDataSourceProxy,
         which can dynamically discover the transaction context -->
    <bean id="transactionAwareDataSource"
        
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
        <constructor-arg ref="dataSource_mysql" />
    </bean>

    <bean class="org.jooq.impl.DataSourceConnectionProvider" 
name="connectionProvider">
        <constructor-arg ref="transactionAwareDataSource" />
    </bean>
    
    <bean id="exceptionTranslator" 
class="com.westhouse.jooq.exception.ExceptionTranslator" />
    
    <!-- Invoking an internal, package-private constructor for the example
         Implement your own Configuration for more reliable behaviour -->
    <bean class="org.jooq.impl.DefaultConfiguration" name="config">
        <constructor-arg index="0" ref="connectionProvider" />
        <constructor-arg index="1"><null /></constructor-arg>
        <constructor-arg index="2"><null /></constructor-arg>
        <constructor-arg index="3">
            <list>
                <bean class="org.jooq.impl.DefaultExecuteListenerProvider">
                    <constructor-arg index="0" ref="exceptionTranslator"/>
                </bean>
            </list>
        </constructor-arg>
        <constructor-arg index="4"><null /></constructor-arg>
        <constructor-arg index="5"><value 
type="org.jooq.SQLDialect">MARIADB</value></constructor-arg>
        <constructor-arg index="6"><null /></constructor-arg>
        <constructor-arg index="7"><null /></constructor-arg>
    </bean>
    
    <!-- Configure the DSL object, optionally overriding jOOQ Exceptions 
with Spring Exceptions -->
    <bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
        <constructor-arg ref="config" />
    </bean>
    <!-- joo end -->


in order to provide the general MyRecordRowMapperProvider i dont like to 
reconfig everything using:

DSL.using(new DefaultConfiguration()
   .set(connection)
   .set(SQLDialect.ORACLE)


. Is there a way to specify the provider in the spring.xml configuration of 
the constructor? perhaps as the third constructor argument as a reference 
to the MyRecordRowMapperProvider bean?

The provider goes into the right direction of centralizing my mappers, but 
its not yet the best solution. Is there an abstract class of the 
RecordMapperProvider interface also available? I´m asking as i like it more 
to specify the parameter class
directly to get a specific AccountRecordMapperProvider instead of a generic 
method where i have to conditionally ask for each class type and eventually 
return the defaultrecordmapper instead of throwing an exception,
when the appriopriate class mapper cannot be found, which IMO leads to bad 
behaviour.

if (type == Account.class) {
return (RecordMapper<R, E>) getAccountRecordMapper();
}
return new DefaultRecordMapper(recordType, type);



 I dont think the default mapper could not map anything right in my cases, 
the fallback therefor is for me more pain than gain.
maybe this thoughts are a leftover excessive spring row mapper using, but 
it just somehow feels bad.

share your thoughts!

best regards

stefan





Am Donnerstag, 18. Dezember 2014 18:43:47 UTC+1 schrieb Lukas Eder:
>
> Hi Stefan,
>
> Re-normalising the outcome of joins is a frequent topic on this user 
> group. I'm glad you have also listed the possibility of running two 
> queries, the second one taking the first query in a semi-join using an 
> IN-predicate, which is probably the best way of doing this with SQL, short 
> of using MULTISETs.
>
> Concerning your actual question, there is a possibility to override jOOQ's 
> DefaultRecordMapper centrally for all queries via a RecordMapperProvider 
> that you can register in your Configuration:
>
> http://www.jooq.org/doc/latest/manual/sql-execution/fetching/pojos-with-recordmapper-provider/
>
> From how I understand your use-case, you will be able to delegate some 
> mapping to your own reusable RecordMappers once and for all, while 
> delegating unknown mapping targets to jOOQ's DefaultRecordMapper, or 
> perhaps to modelmapper.
>
> Let me know if this is what you were looking for. In my opinion, this 
> should allow for you to implement a solution that's even simpler to use at 
> the call site than Spring's RowMapper.
>
> Best Regards,
> Lukas
>
> 2014-12-18 11:35 GMT+01:00 gantners <stefan...@live.de <javascript:>>:
>>
>> I would like to use jooq for building the sql and  replacing the pure 
>> spring jdbc calls with all those ugly ? on update statements and also 
>> getting more typesafety.
>>
>> Currently I use Spring and its RowMapping Functionality. 
>>
>>
>> class Contact{
>> int uniqueId;
>> String name;
>> Account account;
>> }
>>
>>
>> class Account{
>> int id;
>> String name;
>> }
>>
>>
>>
>> public List<Contact> getContactListByUniqueID(List<String> uniqueids) {
>>  Map<String, List<String>> namedParameters = Collections.singletonMap(
>> "ids", uniqueids);
>>  return SQLUtils.namedListQuery(namedParameterJdbcTemplate,"Select* from 
>> contact left join account on contact.accountid = account.id where 
>> UniqueID in (:ids)",namedParameters,RowMapperFactory.getContactRowMapper
>> ());
>> }
>>
>> }
>>
>> with:
>>
>> public static RowMapper<Contact> getContactRowMapper(){
>>
>>             return new RowMapper<Contact>() {
>>                    public Contact mapRow(ResultSet rs, int rowNum) throws 
>> SQLException, DataAccessException {
>>                                 Contact c = new Contact();
>>                                 c.setFirstname(rs.getString(Contact.
>> Firstname));
>>                                 //fill all
>>                                 c.setAccount(RowMapperFactory.
>> getAccountRowMapper().mapRow(rs,rowNum)); //AccountMapper same style as 
>> ContactMapper
>>                                 return c;
>>                         }
>> }
>>
>>
>> For convenience, i build the beans using the cartesian product over 
>> joins, for entities which have none to few "one to one" foreign keys.
>> This approach gets unhandy if the beans consists of many other beans 
>> which lead to many joins.
>>
>> To address this issue, i´d like to normalize this by doing a single query 
>> each:
>>
>> select * from contact where uniqueid in (:ids);
>> select * from account where id in (select accountid from contact where 
>> uniqueid in (:ids));
>>
>>
>>
>> The questions:
>>
>> a) i find it unhandy to iterate over the first contact list to map the 
>> according account from the second query. Is there a much better approach to 
>> set each contacts account?
>> b) i had a look into modelmapper, but i´m not sure which approach to take 
>> for mapping my rows to bean, as modelmapper needs a lot of code for doing 
>> this (for reasons i need to specify each mapping property extra, as the 
>> table columns are not matching any strategy like camelcase etc. and also i 
>> have some legacy strings which are boolean in the bean) 
>>
>> What i want to achieve is some sort of factory providing me the mapping 
>> in a way, that i do not have to think about it in any other place like my 
>> current RowMapperFactory.
>> I imagine something like:
>>
>> create.selectFrom(BOOK).orderBy(BOOK.ID).fetch().map(new RecordMapper<
>> BookRecord, Integer>() { 
>>          @Override public Integer map(BookRecord book) { 
>>               return book.getId(); 
>>          }
>>  };
>>
>>
>> But the RecordMapper as Factory like my RowMapperFactory, to have a 
>> central place for all mappers which can be used anywhere in all daos like:
>>
>>
>> public static RecordMapper<ContactRecord, Contact> getContactRowMapper(){ 
>> return new RecordMapper<ContactRecord, Contact>() { 
>> @Override public Contact map(ContactRecord record) { 
>> Contact c = new Contact(); 
>> c.setFirstname(record.getValue(table.Firstname)); //whereever i would get 
>> the table from 
>> return c; } 
>> }
>> }
>> }
>>
>> that way i would save a lot of converters, providers which i think would 
>> be necessary if i use modelmapper. Maybe i just didn´t see the easy way 
>> with it.
>> So i´m looking forward on your oppion.
>>
>> Cheers Stefan
>>
>>
>>
>>  -- 
>> You received this message because you are subscribed to the Google Groups 
>> "jOOQ User Group" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to jooq-user+...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jooq-user+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to