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

org.simpleflatmapper.jdbc.impl.AbstractBatchInsertQueryExecutor Maven / Gradle / Ivy

package org.simpleflatmapper.jdbc.impl;

import org.simpleflatmapper.converter.Context;
import org.simpleflatmapper.converter.ContextFactory;
import org.simpleflatmapper.jdbc.MultiIndexFieldMapper;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.CheckedConsumer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;

public abstract class AbstractBatchInsertQueryExecutor implements BatchQueryExecutor {
    protected final String[] insertColumns;
    protected final String[] insertColumnExpressions;
    protected final String[] updateColumns;
    protected final String[] generatedKeys;
    
    protected final MultiIndexFieldMapper[] multiIndexFieldMappers;
    protected final ContextFactory contextFactory;
    private final CrudMeta meta;

    public AbstractBatchInsertQueryExecutor(CrudMeta meta, String[] insertColumns, String[] insertColumnExpressions, String[] updateColumns, String[] generatedKeys, MultiIndexFieldMapper[] multiIndexFieldMappers, ContextFactory contextFactory) {
        this.meta = meta;
        this.insertColumns = insertColumns;
        this.insertColumnExpressions = insertColumnExpressions;
        this.updateColumns = updateColumns;
        this.generatedKeys = generatedKeys;
        this.multiIndexFieldMappers = multiIndexFieldMappers;
        this.contextFactory = contextFactory;
    }

    @Override
    public void insert(Connection connection, Collection values, CheckedConsumer postExecute) throws SQLException {
        PreparedStatement preparedStatement = prepareStatement(connection, values.size());
        try {
            bindTo(preparedStatement, values);
            preparedStatement.executeUpdate();
            postExecute.accept(preparedStatement);
        } catch (Exception e) {
            ErrorHelper.rethrow(e);
        } finally {
            try {
                preparedStatement.close();
            } catch(SQLException e) {
                // IGNORE
            }
        }
    }

    private PreparedStatement prepareStatement(Connection connection, int batchSize) throws SQLException {
        StringBuilder sb = createQuery(batchSize);
        if (generatedKeys.length == 0) {
            return connection.prepareStatement(sb.toString());
        } else {
            return connection.prepareStatement(sb.toString(), generatedKeys);
        }
    }

    private StringBuilder createQuery(int size) {
        StringBuilder sb = new StringBuilder();

        insertInto(sb);
        values(size, sb);
        if (updateColumns != null) {
            onDuplicateKeys(sb);
        }

        return sb;
    }

    protected abstract void onDuplicateKeys(StringBuilder sb);

    private void values(int size, StringBuilder sb) {
        sb.append(" VALUES");
        for(int i = 0; i < size; i++) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append("(");

            appendValueExpressions(sb);

            sb.append(")");

        }
    }

    private void appendValueExpressions(StringBuilder sb) {
        for(int j = 0; j < insertColumns.length; j++) {
            if (j > 0) {
                sb.append(", ");
            }
            if (insertColumnExpressions == null || insertColumnExpressions[j] == null) {
                sb.append("?");
            } else {
                sb.append(insertColumnExpressions[j]);
            }
        }
    }

    private void insertInto(StringBuilder sb) {
        appendInsertInto(sb);
        meta.appendTableName(sb);
        sb.append("(");

        for(int j = 0; j < insertColumns.length; j++) {
            if (j > 0) {
                sb.append(", ");
            }
            sb.append(insertColumns[j]);
        }

        sb.append(")");
    }

    protected void appendInsertInto(StringBuilder sb) {
        sb.append("INSERT INTO ");
    }

    private void bindTo(PreparedStatement preparedStatement, Collection values) throws Exception {
        int i = 0;
        Context context = contextFactory.newContext();
        for(T value : values) {
            for (MultiIndexFieldMapper multiIndexFieldMapper : multiIndexFieldMappers) {
                multiIndexFieldMapper.map(preparedStatement, value, i, context);
                i++;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy