org.simpleflatmapper.jdbc.JdbcMapperFactory Maven / Gradle / Ivy
package org.simpleflatmapper.jdbc;
import org.simpleflatmapper.map.ContextualSourceFieldMapper;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.getter.ContextualGetterFactory;
import org.simpleflatmapper.map.getter.ContextualGetterFactoryAdapter;
import org.simpleflatmapper.map.mapper.AbstractColumnNameDiscriminatorMapperFactory;
import org.simpleflatmapper.map.mapper.DynamicSourceFieldMapper;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.jdbc.impl.JdbcColumnKeyMapperKeyComparator;
import org.simpleflatmapper.jdbc.impl.PreparedStatementSetterFactory;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.SetRowMapper;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.map.mapper.AbstractMapperFactory;
import org.simpleflatmapper.map.mapper.ConstantTargetFieldMapperFactoryImpl;
import org.simpleflatmapper.map.mapper.DynamicSetRowMapper;
import org.simpleflatmapper.map.mapper.FieldMapperColumnDefinitionProviderImpl;
import org.simpleflatmapper.map.mapper.MapperKey;
import org.simpleflatmapper.util.TypeHelper;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.util.UnaryFactory;
import org.simpleflatmapper.util.UnaryFactoryWithException;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
/**
* JdbcMapperFactory allows you to customise the mappers and create an newInstance of it using a fluent syntax.
*
* JdbcMapperFactory is not Thread-Safe but the mappers are.
* It is strongly advised to instantiate one jdbcMapper per class for the life of your application.
*
* You can instantiate dynamic jdbcMapper which will use the ResultSetMetaData
* to figure out the list of the columns or a static one using a builder.
*
*
* // create a dynamic jdbcMapper targeting MyClass
* JdbcMapperFactory
* .newInstance()
* .newMapper(MyClass.class);
*
* // create a static jdbcMapper targeting MyClass
* JdbcMapperFactory
* .newInstance()
* .newBuilder(MyClass.class)
* .addMapping("id")
* .addMapping("field1")
* .addMapping("field2")
* .mapper();
*
*
*
*/
public final class JdbcMapperFactory
extends AbstractColumnNameDiscriminatorMapperFactory {
/**
* instantiate a new JdbcMapperFactory
* @return a new newInstance JdbcMapperFactory
*/
public static JdbcMapperFactory newInstance() {
return new JdbcMapperFactory();
}
public static JdbcMapperFactory newInstance(
AbstractMapperFactory config) {
return new JdbcMapperFactory(config);
}
private JdbcMapperFactory(AbstractMapperFactory config) {
super(config);
}
private JdbcMapperFactory() {
super(new FieldMapperColumnDefinitionProviderImpl(), FieldMapperColumnDefinition.identity(), new ContextualGetterFactoryAdapter(ResultSetGetterFactory.INSTANCE));
}
/**
* Override the default implementation of the GetterFactory used to get access to value from the ResultSet.
* @param getterFactory the getterFactory
* @return the current factory
*/
public JdbcMapperFactory getterFactory(final GetterFactory getterFactory) {
return addGetterFactory(new ContextualGetterFactoryAdapter(getterFactory));
}
/**
* Override the default implementation of the GetterFactory used to get access to value from the ResultSet.
* @param getterFactory the getterFactory
* @return the current factory
*/
public JdbcMapperFactory addGetterFactory(final ContextualGetterFactory getterFactory) {
return super.addGetterFactory(getterFactory);
}
/**
* Associate the specified FieldMapper for the specified property.
* @param key the property
* @param fieldMapper the fieldMapper
* @return the current factory
*/
public JdbcMapperFactory addCustomFieldMapper(String key, FieldMapper fieldMapper) {
return addColumnDefinition(key, FieldMapperColumnDefinition.customFieldMapperDefinition(fieldMapper));
}
/**
* Associate the specified Getter for the specified property.
* @param key the property
* @param getter the getter
* @return the current factory
*/
public JdbcMapperFactory addCustomGetter(String key, Getter getter) {
return addColumnDefinition(key, FieldMapperColumnDefinition.customGetter(getter));
}
/**
* Will create a newInstance of JdbcMapper based on the specified metadata and the target class.
* @param target the target class of the jdbcMapper
* @param metaData the metadata to create the jdbcMapper from
* @param the jdbcMapper target type
* @return a jdbcMapper that will map the data represented by the metadata to an newInstance of target
* @throws java.sql.SQLException if an error occurs getting the metaData
*/
public JdbcMapper newMapper(final Class target, final ResultSetMetaData metaData) throws SQLException {
JdbcMapperBuilder builder = newBuilder(target);
builder.addMapping(metaData);
return builder.mapper();
}
/**
* Will create a newInstance of JdbcMapperBuilder on the specified target class.
* @param target the target class
* @param the jdbcMapper target type
* @return the builder
*/
public JdbcMapperBuilder newBuilder(final Class target) {
return newBuilder((Type)target);
}
/**
* Will create a newInstance of JdbcMapperBuilder on the type T specified by the typeReference.
* @param target the typeReference
* @param the jdbcMapper target type
* @return the builder
*/
public JdbcMapperBuilder newBuilder(final TypeReference target) {
return newBuilder(target.getType());
}
/**
* Will create a newInstance of JdbcMapperBuilder on the specified type.
* @param target the type
* @param the jdbcMapper target type
* @return the builder
*/
public JdbcMapperBuilder newBuilder(final Type target) {
ClassMeta classMeta = getClassMeta(target);
return newBuilder(classMeta);
}
public JdbcMapperBuilder newBuilder(ClassMeta classMeta) {
MapperConfig mapperConfig = mapperConfig(classMeta.getType());
return new JdbcMapperBuilder(
classMeta,
mapperConfig,
getterFactory,
new JdbcMappingContextFactoryBuilder(!mapperConfig.unorderedJoin()));
}
/**
*
* @param target the type
* @param the type
* @return a builder to create a mapper from target to PreparedStatement
*/
public PreparedStatementMapperBuilder buildFrom(final Class target) {
return buildFrom((Type) target);
}
public PreparedStatementMapperBuilder buildFrom(final Type target) {
ClassMeta classMeta = getClassMeta(target);
return buildFrom(classMeta);
}
public PreparedStatementMapperBuilder buildFrom(final TypeReference target) {
return buildFrom(target.getType());
}
public PreparedStatementMapperBuilder buildFrom(final ClassMeta classMeta) {
return new PreparedStatementMapperBuilder(classMeta, mapperConfig(classMeta.getType()), ConstantTargetFieldMapperFactoryImpl.newInstance(PreparedStatementSetterFactory.INSTANCE, PreparedStatement.class));
}
public PreparedStatementMapperBuilder from(final Class target) {
return buildFrom(target);
}
public PreparedStatementMapperBuilder from(final Type target) {
return buildFrom(target);
}
public PreparedStatementMapperBuilder from(final TypeReference target) {
return buildFrom(target);
}
public PreparedStatementMapperBuilder from(final ClassMeta classMeta) {
return buildFrom(classMeta);
}
/**
* Will create a DynamicMapper on the specified target class.
* @param target the class
* @param the jdbcMapper target type
* @return the DynamicMapper
*/
public DynamicJdbcMapper newMapper(final Class target) {
return newMapper((Type) target);
}
/**
* Will create a DynamicMapper on the type specified by the TypeReference.
* @param target the TypeReference
* @param the jdbcMapper target type
* @return the DynamicMapper
*/
public DynamicJdbcMapper newMapper(final TypeReference target) {
return newMapper(target.getType());
}
public CrudDSL crud(final Type target, final Type keyTarget) {
return crud(this.getClassMeta(target), this.getClassMeta(TypeHelper.toBoxedClass(keyTarget)));
}
public CrudDSL crud(final ClassMeta target, final ClassMeta keyTarget) {
return new CrudDSL(target, keyTarget, JdbcMapperFactory.newInstance(this));
}
public CrudDSL crud(final Class target, final Class keyTarget) {
return crud((Type)target, (Type)keyTarget);
}
/**
* Will create a DynamicMapper on the specified type.
* @param target the type
* @param the jdbcMapper target type
* @return the DynamicMapper
*/
public DynamicJdbcMapper newMapper(final Type target) {
final ClassMeta classMeta = getClassMeta(target);
return new DynamicJdbcSetRowMapper(new SetRowMapperFactory(classMeta), new MapperKeyFactory(), new MapperKeyFactory());
}
public JdbcSourceFieldMapper newSourceFieldMapper(Type target) {
final ClassMeta classMeta = getClassMeta(target);
return new DynamicJdbSourceFieldMapper(new SourceFieldMapperFactory(classMeta), new MapperKeyFactory());
}
public static class DynamicJdbSourceFieldMapper
extends DynamicSourceFieldMapper
implements JdbcSourceFieldMapper {
public DynamicJdbSourceFieldMapper(
UnaryFactory, ContextualSourceFieldMapper> mapperFactory,
UnaryFactoryWithException, SQLException> mapperKeyFromRow) {
super(mapperFactory, mapperKeyFromRow, JdbcColumnKeyMapperKeyComparator.INSTANCE);
}
private ContextualSourceFieldMapper getMapper(ResultSetMetaData metaData) throws SQLException {
return getMapper(JdbcColumnKey.mapperKey(metaData));
}
@Override
public String toString() {
return "DynamicJdbcSetRowMapper{}";
}
@Override
public MappingContext super ResultSet> newMappingContext(ResultSet resultSet) throws SQLException {
JdbcSourceFieldMapper mapper = (JdbcSourceFieldMapper) getMapper(resultSet.getMetaData());
return mapper.newMappingContext(resultSet);
}
}
public static class DynamicJdbcSetRowMapper
extends DynamicSetRowMapper
implements DynamicJdbcMapper {
public DynamicJdbcSetRowMapper(
UnaryFactory, SetRowMapper> mapperFactory,
UnaryFactoryWithException, SQLException> mapperKeyFromRow,
UnaryFactoryWithException, SQLException> mapperKeyFromSet) {
super(mapperFactory, mapperKeyFromRow, mapperKeyFromSet, JdbcColumnKeyMapperKeyComparator.INSTANCE);
}
@Override
public JdbcMapper getMapper(ResultSetMetaData metaData) throws SQLException {
return (JdbcMapper) getMapper(JdbcColumnKey.mapperKey(metaData));
}
@Override
public String toString() {
return "DynamicJdbcSetRowMapper{}";
}
@Override
public MappingContext super ResultSet> newMappingContext(ResultSet resultSet) throws SQLException {
return getMapper(resultSet.getMetaData()).newMappingContext(resultSet);
}
}
/**
* Create a discriminator builder based on the specified property
* @param column the discriminator property
* @param the root type of the jdbcMapper
* @return a builder to specify the type mapping
*/
public DiscriminatorJdbcBuilder newDiscriminator(String column) {
ignorePropertyNotFound();
addColumnDefinition(column, FieldMapperColumnDefinition.ignoreDefinition());
return new DiscriminatorJdbcBuilder(column, this);
}
private static class MapperKeyFactory implements UnaryFactoryWithException, SQLException> {
@Override
public MapperKey newInstance(ResultSet set) throws SQLException {
return JdbcColumnKey.mapperKey(set.getMetaData());
}
}
private class SetRowMapperFactory implements UnaryFactory, SetRowMapper> {
private final ClassMeta classMeta;
public SetRowMapperFactory(ClassMeta classMeta) {
this.classMeta = classMeta;
}
@Override
public SetRowMapper newInstance(MapperKey jdbcColumnKeyMapperKey) {
final JdbcMapperBuilder builder = newBuilder(classMeta);
for(JdbcColumnKey key : jdbcColumnKeyMapperKey.getColumns()) {
builder.addMapping(key);
}
return builder.mapper();
}
}
private class SourceFieldMapperFactory implements UnaryFactory, ContextualSourceFieldMapper> {
private final ClassMeta classMeta;
public SourceFieldMapperFactory(ClassMeta classMeta) {
this.classMeta = classMeta;
}
@Override
public ContextualSourceFieldMapper newInstance(MapperKey jdbcColumnKeyMapperKey) {
final JdbcMapperBuilder builder = newBuilder(classMeta);
for(JdbcColumnKey key : jdbcColumnKeyMapperKey.getColumns()) {
builder.addMapping(key);
}
return builder.newSourceFieldMapper();
}
}
}