Использование QueryRunner для вставки ArrayList <Object []> - PullRequest
3 голосов
/ 26 июля 2011

Я хочу использовать QueryRunner для выполнения вставки ArrayList.Единственная информация, которую я нахожу в Интернете, - это вставка одного объекта [].Что-то вроде:

qr.update("insert into MyTable (param1,param2,param3) values (?,?,?)",
new Object[] { str1, str2, str3});

Я бы, очевидно, хотел бы избежать необходимости циклически проходить по всему списку ArrayList и вставлять по одному индексу за раз, поскольку число вставляемых строк каждый раз неизвестно.

Я просто хотел посмотреть, сделал ли кто-нибудь это.Запрос возвращает список, поэтому я не понимаю, почему я не могу вставить список.Любые предложения приветствуются.Спасибо.

Ответы [ 2 ]

7 голосов
/ 17 июля 2012

Я знаю, что это старый, но я искал информацию о Apache Commons DBUtils QueryRunner и наткнулся на это ... Для дальнейшего использования вы можете:

Сначала преобразуйте ArrayList в объект [] []:

Object[][] params = null;
params = listOfObjectArrays.toArray(params);

Затем передайте params пакетному методу в QueryRunner (возвращает int []):

qr.batch("insert into MyTable (param1,param2,param3) values (?,?,?)", params);
2 голосов
/ 10 августа 2016

Я тоже с этим боролся, но решил создать модель ToSqlConverter.Это не самый красивый код, который я когда-либо писал, но он работает как шарм.

Я действительно создал небольшую оболочку для Dbutils, которую я называю GenericDataAccessor.Это работа в процессе, и я выложу ее на github, как только у меня будет время.Это отличный инструмент для всех проектов среднего размера, который кажется маленьким для реального ORM, такого как Hibernate, но большим - просто для использования JDBC.Любой как.Не стесняйтесь использовать это, если хотите, это мне очень помогло.

Вот ModelConverter

    /**
 * The <code>ModelToSqlConverter</code> class <br>
 * <br>
 * Deserializes the model and creates the sql string for update and insert.<br>
 * Also generates the object array for the values from the model.
 */
public class ModelToSqlConverter{

    private Object model;

    private List<Object> params, keyParams, modelList;

    private String fieldNameString, questionMarkString, sqlString, conditionString, updateString;

    private boolean update;

    private String[] keys;

    private Object[][] multiParams;

    /**
     * Initializes a newly created <code>ModelToSqlConverter</code>
     *
     * @param model The model representing the ASW file.
     * @param keys The keys for locating the right row in ASW file.
     */
    @SuppressWarnings("unchecked")
    private ModelToSqlConverter(Object model, String... keys){
        this.model = model;
        this.keys = keys;
        params = new ArrayList<>();
        keyParams = new ArrayList<>();
        questionMarkString = "VALUES (";
        fieldNameString = "(";
        updateString = "";
        conditionString = "WHERE ";
        update = keys != null && keys.length > 0;
        if(model instanceof List<?>){
            modelList = (List<Object>) model;
            convertModelListToSqlAndParams();
        }else{
            convertModelToSqlAndParams();
        }

    }

    /**
     * Main method for Converting Model into SQL String and to value parameters.
     */
    private void convertModelToSqlAndParams(){

        for(Field field : model.getClass().getDeclaredFields()){
            try{
                field.setAccessible(true);
                Object value = field.get(model);
                String fieldName = field.getName();
                if(value != null && !fieldName.equalsIgnoreCase("serialVersionUID")){
                    if(!update){
                        addQuestionMark();
                        addNameToSql(fieldName);
                        addValueToObjectArray(value);
                    }else{
                        if(isKey(fieldName)){
                            conditionString += fieldName + " = ?,";
                            keyParams.add(value);

                        }else{
                            addParamAndNameToSql(fieldName);
                            addValueToObjectArray(value);
                        }
                    }
                }

            }catch(IllegalArgumentException e){
                // TODO Auto-generated catch block
                e.printStackTrace();
            }catch(IllegalAccessException e){
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        sqlString = update ? getUpdateSql() : getInsertSql();
        for(Object key : keyParams){
            addValueToObjectArray(key);
        }
    }

    /**
     * Main method for Converting Model into SQL String and to value parameters.
     */
    private void convertModelListToSqlAndParams(){
        int row = 0;
        boolean isKey = false;
        boolean firstModel = true;
        Field[] fields = modelList.get(0).getClass().getDeclaredFields();
        multiParams = new Object[modelList.size()][fields.length];
        for(Object model : modelList){
            int col = 0;
            keyParams = new ArrayList<>();
            for(Field field : fields){
                try{
                    field.setAccessible(true);
                    Object value = field.get(model);
                    String fieldName = field.getName();
                    if(value != null && !fieldName.equalsIgnoreCase("serialVersionUID")){
                        if(!update){
                            if(firstModel){
                                addQuestionMark();
                                addNameToSql(fieldName);
                            }
                            addValueToMultiParams(value, row, col);
                        }else{
                            isKey = isKey(fieldName);
                            if(isKey){
                                if(firstModel){
                                    conditionString += fieldName + " = ?,";
                                }
                                keyParams.add(value);
                            }else{
                                if(firstModel)
                                    addParamAndNameToSql(fieldName);
                                addValueToMultiParams(value, row, col);
                            }
                        }
                    }

                }catch(IllegalArgumentException e){
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }catch(IllegalAccessException e){
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                if(!isKey)
                    col++;
            }
            firstModel = false;
            for(Object key : keyParams){
                addValueToMultiParams(key, row, col);
                col++;
            }
            row++;
        }
        sqlString = update ? getUpdateSql() : getInsertSql();

    }

    /**
     * @param columnName
     */
    private void addNameToSql(String columnName){
        fieldNameString += columnName + ",";
    }

    /**
     * @param value
     */
    private void addValueToObjectArray(Object value){
        params.add(value);
    }

    /**
     * @param value
     * @param row
     * @param col
     */
    private void addValueToMultiParams(Object value, int row, int col){
        multiParams[row][col] = value;
    }

    public Object[][] getMultiValueParams(){
        return removeNullsFromMultiArray(multiParams);
    }

    /**
     * Adds question mark to string
     */
    private void addQuestionMark(){
        questionMarkString += "?,";
    }

    /**
     * @param columnName
     */
    private void addParamAndNameToSql(String columnName){
        updateString += columnName + "= ?,";
    }

    /**
     * @return the update SQL string.
     */
    private String getUpdateSql(){
        return updateString.substring(0, updateString.lastIndexOf(",")) + " " + conditionString.substring(0, conditionString.lastIndexOf(","));
    }

    /**
     * @return the insert SQL string.
     */
    private String getInsertSql(){
        return fieldNameString.substring(0, fieldNameString.lastIndexOf(",")) + ") " + questionMarkString.substring(0, questionMarkString.lastIndexOf(","))
                + ")";
    }

    private Object[][] removeNullsFromMultiArray(Object[][] multiValuedArray){
        for(int i = 0; i < multiValuedArray.length; i++){
            ArrayList<Object> list = new ArrayList<Object>(); // creates a list to store the elements !=
                                                                // null
            for(int j = 0; j < multiValuedArray[i].length; j++){
                if(multiValuedArray[i][j] != null){
                    list.add(multiValuedArray[i][j]); // elements != null will be added to the list.
                }
            }
            multiValuedArray[i] = list.toArray(new Object[list.size()]); // all elements from list to an
                                                                            // array.
        }
        return multiValuedArray;
    }

    /**
     * Checks if the field name is a key.
     * 
     * @param fieldName
     * @return true if the field is a key.
     */
    private boolean isKey(String fieldName){
        boolean isKey = false;
        for(String key : keys){
            if(fieldName.equalsIgnoreCase(key)){
                isKey = true;
            }
        }
        return isKey;
    }

    /**
     * @return the params
     */
    public Object[] getParams(){
        return params.toArray();
    }

    /**
     * @return the sqlString
     */
    public String getSqlString(){
        return sqlString;
    }

    /**
     * @param params the params to set
     */
    public void setParams(List<Object> params){
        this.params = params;
    }

    /**
     * @param sqlString the sqlString to set
     */
    public void setSqlString(String sqlString){
        this.sqlString = sqlString;
    }

}

А вот метод, который вы вызываете для вставки.

/**
 * Insert batch of rows from model list into the Database.
 * 
 * @param modelsList List of model objects representing the Database table.
 * @return int Array of inserted rows.
 * @throws SQLException
 */
public <T> int[] insertWithListOfModels(List<T> modelsList) throws SQLException{
    ModelToSqlConverter modelConverter = new ModelToSqlConverter(modelsList);
    QueryRunner qryRunner = new QueryRunner();
    int[] inserts = null;
    System.out.println("INSERT INTO " + modelsList.get(0).getClass().getSimpleName().toUpperCase() + " " + modelConverter.getSqlString());
    System.out.println(Arrays.deepToString(modelConverter.getMultiValueParams()));
    inserts = qryRunner.batch(connection,
            "INSERT INTO " + modelsList.get(0).getClass().getSimpleName().toUpperCase() + " " + modelConverter.getSqlString(),
            modelConverter.getMultiValueParams());
    return inserts;
}

Как это работает, вы отправляете либо список моделей, либо просто один объект.Метод, который я предоставил, предназначен для обновления списка моделей, но вы поняли идею.Конструктор modelToSqlConvertor обрабатывает все.Затем с помощью dbutils qryRunner вы объявляете свой sql и вызываете получатели из modelToSqlConverter для значений и параметров.

Чтобы эта работа работала, ваша модель должна быть идентична вашей таблице базы данных.Я создал свои модели с помощью JPA.

Надеюсь, это поможет!

...