Hello Alok, Thank you for your detailed E-Mail. I'm commenting inline
2015-04-21 23:53 GMT+02:00 Alok Menghrajani <[email protected]>: > Hi, > > I want to check if anyone has a suggestion on using .map() with > .join() in the query. > > If you look at the fetchXYZ methods in [1], you'll notice that: > > fetchAuthors is fine. It's the simplest case and works as expected. > > > fetchOneAuthor fails to type check if you use MyTypedMapper. I > initially thought the root cause was the signature of the map method > (it's <E> List<E> map(RecordMapper<? super R, E> var1); in Result.java > but public final <E> E map(RecordMapper<Record, E> mapper) in > AbstractRecord). I however gave up trying to fix this issue as I > clearly don't know type systems. > This is due to a design restriction we have been struggling with for a while. We cannot refer to the generic R type of a Record from within the record, as we don't declare the generic type recursively. If we wanted to get this right for the Record.map() method, we would have to declare: interface Record<R extends Record> { } However, recursive generics are pandora's box that you generally don't want to open, especially in a type hierarchy like that of Record. I've blogged about this here: http://blog.jooq.org/2013/06/28/the-dangers-of-correlating-subtype-polymorphism-with-generic-polymorphism/ This will be addressed in jOOQ 4.0: https://github.com/jOOQ/jOOQ/issues/2570 I suspect that by using a type similar to Optional<T>, we could properly solve this. In fact, you could actually use Optional: Optional.of(record).map(myTypedMapper::map).get(); // or: Optional.of(record).map(r -> myTypedMapper.map(r)).get(); // or just plain old ;-) myTypedMapper.map(record); A (silly) workaround would be to operate only with Result<R>, which doesn't have this limitation. The maven error message is fantastically useful: > error: method map in class AbstractRecord cannot be applied to given types; > > > fetchAuthorsOfTitle is the interesting case. It is a common pattern in > the codebase I'm working on. The .join() is not used to fetch more > data, but only to filter data / enforce privacy rules. > Interesting. Is there a reason why you didn't semi-join that relation, e.g. via IN or EXISTS? Performance, perhaps? Is there a way to avoid having to use an untyped mapper? Can I tell > jOOQ that I want to select on a table and that join should not change > the type of the Record? > You're looking for Result.into(Table), or ResultQuery.fetchInto(Table): - http://www.jooq.org/javadoc/latest/org/jooq/Result.html#into-org.jooq.Table- - http://www.jooq.org/javadoc/latest/org/jooq/ResultQuery.html#fetchInto-org.jooq.Table- You can use these methods with any query. It will produce records of type R from Table<R>, containing only the columns of R, or null if the column name wasn't present in the result. > fetchOneAuthorWithTransaction is interesting because mvn does not > properly infer the type of Immutable.of() so I need to write > Immutable.<MyAuthor>of(). Intellij doesn't complain. It's not a jOOQ > specific thing, just a quirk which shows up when using closures (which > transactions encourage). I guess it's something that should be filed > as a bug with JetBrains. > There had been a lot of bugs in the javac compiler that have all been fixed in 1.8.0_40... I can't reproduce this particular one anymore, but I remember having run into this kind of type inference problem with 1.8.0_25 and earlier. Cheers, Lukas -- 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
