All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sfm.jdbc.spring.SqlParameterSourceBuilder Maven / Gradle / Ivy

There is a newer version: 9.0.2
Show newest version
package org.sfm.jdbc.spring;

import org.sfm.jdbc.JdbcColumnKey;
import org.sfm.map.MapperBuilderErrorHandler;
import org.sfm.map.MapperConfig;
import org.sfm.map.PropertyWithGetter;
import org.sfm.map.column.ConstantValueProperty;
import org.sfm.map.column.FieldMapperColumnDefinition;
import org.sfm.map.error.RethrowMapperBuilderErrorHandler;
import org.sfm.map.mapper.DefaultPropertyNameMatcherFactory;
import org.sfm.map.mapper.PropertyMapping;
import org.sfm.map.mapper.PropertyMappingsBuilder;
import org.sfm.reflect.ReflectionService;
import org.sfm.reflect.ScoredGetter;
import org.sfm.reflect.TypeHelper;
import org.sfm.reflect.impl.ConstantGetter;
import org.sfm.reflect.meta.ClassMeta;
import org.sfm.reflect.meta.ObjectPropertyMeta;
import org.sfm.reflect.meta.PropertyMeta;
import org.sfm.reflect.meta.PropertyNameMatcherFactory;
import org.sfm.utils.ErrorHelper;
import org.sfm.utils.ForEachCallBack;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;

import java.lang.reflect.Field;
import java.util.List;

public final class SqlParameterSourceBuilder {


    private final PropertyMappingsBuilder> builder;
    private final MapperConfig> mapperConfig;
    private final ReflectionService reflectionService;
    private int index = 1;

    private static final Field paramNamesField;
    static {
        Field f = null;
        try {
            f = ParsedSql.class.getDeclaredField("parameterNames");
            f.setAccessible(true);
        } catch (Exception e) {
            // ignore
        }
        paramNamesField = f;
    }

    public SqlParameterSourceBuilder(
            ClassMeta classMeta,
            MapperConfig> mapperConfig) {
        this.mapperConfig = mapperConfig;
        this.reflectionService = classMeta.getReflectionService();
        this.builder =
                new PropertyMappingsBuilder>(
                        classMeta,
                        mapperConfig.propertyNameMatcherFactory(),
                        mapperConfig.mapperBuilderErrorHandler(),
                        new PropertyWithGetter()
                );
    }

    public SqlParameterSourceBuilder add(String column) {
        return add(new JdbcColumnKey(column, index++), FieldMapperColumnDefinition.identity());
    }

    public SqlParameterSourceBuilder add(JdbcColumnKey key, FieldMapperColumnDefinition columnDefinition) {
        final FieldMapperColumnDefinition composedDefinition =
                columnDefinition.compose(mapperConfig.columnDefinitions().getColumnDefinition(key));
        final JdbcColumnKey mappedColumnKey = composedDefinition.rename(key);


        if (composedDefinition.has(ConstantValueProperty.class)) {
            ConstantValueProperty staticValueProperty = composedDefinition.lookFor(ConstantValueProperty.class);
            PropertyMeta meta = new ObjectPropertyMeta(key.getName(), reflectionService, staticValueProperty.getType(), ScoredGetter.of(new ConstantGetter(staticValueProperty.getValue()), 1), null);
            builder.addProperty(key, columnDefinition, meta);
        } else {
            builder.addProperty(mappedColumnKey, composedDefinition);
        }

        return this;
    }

    @SuppressWarnings("unchecked")
    public SqlParameterSourceFactory buildFactory(ParsedSql parsedSql) {
        if (paramNamesField == null) {
            throw new IllegalArgumentException("Unable to gain access to paramNames field in parsedSql");
        }

        try {
            List names = (List) paramNamesField.get(parsedSql);

            for(String name : names) {
                add(name);
            }
        } catch (IllegalAccessException e) {
            ErrorHelper.rethrow(e);
        }
        return buildFactory();
    }

    @SuppressWarnings("unchecked")
    public PlaceHolderValueGetterSource buildSource() {
        final PlaceHolderValueGetter[] parameters = new PlaceHolderValueGetter[builder.size()];
        builder.forEachProperties(
                new ForEachCallBack>>(){
                    int i = 0;
                    @Override
                    public void handle(PropertyMapping> pm) {
                        PlaceHolderValueGetter parameter =
                                new PlaceHolderValueGetter(pm.getColumnKey().getOrginalName(),
                                        StatementCreatorUtils.javaTypeToSqlParameterType(TypeHelper.toClass(pm.getPropertyMeta().getPropertyType())),
                                        null, pm.getPropertyMeta().getGetter());
                        parameters[i] = parameter;
                        i++;
                    }
                });

        return parameters.length > 10
                ? new ArrayPlaceHolderValueGetterSource(parameters)
                : new MapPlaceHolderValueGetterSource(parameters)
                ;
    }

    public SqlParameterSourceFactory buildFactory() {
        return new SqlParameterSourceFactory(buildSource());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy