Skip to content

Instantly share code, notes, and snippets.

@michael-simons
Last active January 22, 2023 00:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michael-simons/5815e24539cc0cb2a923 to your computer and use it in GitHub Desktop.
Save michael-simons/5815e24539cc0cb2a923 to your computer and use it in GitHub Desktop.
A RecordMapperProvider implementation that resolves jOOQ RecordMappers from a Spring Application Context.
import java.util.Map;
import org.jooq.Record;
import org.jooq.RecordMapper;
import org.jooq.RecordMapperProvider;
import org.jooq.RecordType;
import org.jooq.impl.DefaultRecordMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;
/**
* @author Michael J. Simons, 2015-09-08
*/
@Component
public class RecordMapperProviderImpl implements RecordMapperProvider {
private final Map<String, RecordMapper> recordMappers;
@Autowired
public RecordMapperProviderImpl(Map<String, RecordMapper> recordMappers) {
this.recordMappers = recordMappers;
}
@Override
@Cacheable("recordMapper")
public <R extends Record, E> RecordMapper<R, E> provide(RecordType<R> recordType, Class<? extends E> type) {
return recordMappers
.values().stream()
.filter(rm -> {
final ResolvableType resolvableMapperType = ResolvableType.forClass(rm.getClass()).as(RecordMapper.class);
final ResolvableType resolvableRecordType = ResolvableType.forClass(recordType.getClass());
// First check is somewhat redundant, as R is is always resolved to org.jooq.Record due to type erasure
return resolvableRecordType.resolveGeneric(0).isAssignableFrom(resolvableMapperType.resolveGeneric(0))
&& resolvableMapperType.resolveGeneric(1).isAssignableFrom(type);
})
.findFirst()
.orElseGet(() -> new DefaultRecordMapper<>(recordType, type));
}
}
@thomasdarimont
Copy link

Nice :)

You could inject the Map<String, RecordMapper> into a final field directly from the constructor which would enable you to get rid of the ApplicationContext dependency it would also avoid potentially repeated lookups via applicationContext.getBeansOfType(..).

@Autowired
public RecordMapperProviderImpl(Map<String, RecordMapper> recordMappers) {
   this.recordMappers = recordMappers;
}

@michael-simons
Copy link
Author

Awesome, Thomas, thank you!

@michael-simons
Copy link
Author

Thanks @olivergierke for your hint about ResolvableType, didn't know that.

@ivanzito
Copy link

Hi, I'm trying to implement this interface, but in my case I've more than one RecordMapper to a same type. Do you know how can I get the type of RecordType ?

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment