使用 QueryRunner 插入 ArrayList<Object[]>
Posted
技术标签:
【中文标题】使用 QueryRunner 插入 ArrayList<Object[]>【英文标题】:Using QueryRunner to insert ArrayList<Object[]> 【发布时间】:2011-10-13 09:45:27 【问题描述】:我想使用QueryRunner 来插入一个ArrayList。我在网上找到的唯一信息是插入一个 Object[]。大致如下:
qr.update("insert into MyTable (param1,param2,param3) values (?,?,?)",
new Object[] str1, str2, str3);
我显然希望避免遍历整个 ArrayList 并一次插入一个索引,因为每次插入的行数都是未知的。
我只是想看看有没有人这样做过。查询返回一个列表,所以我不明白为什么我不能插入一个列表。任何建议表示赞赏。谢谢。
【问题讨论】:
【参考方案1】:我也在为此苦苦挣扎,但决定创建一个modelToSqlConverter。这不是我写过的最漂亮的代码,但它就像一个魅力。
我实际上已经围绕 Dbutils 创建了一个小包装器,我称之为 GenericDataAccessor。这是一项正在进行的工作,我一有时间就会把它放在 github 上。对于所有中型项目来说,它是一个很棒的工具,对于像 Hibernate 这样的真正 ORM 来说感觉很小,但对于仅使用 JDBC 来说就很大。无论如何。如果您愿意,请随时使用它,它对我有很大帮助。
这里是模型转换器
/**
* 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 调用 getter 获取值和参数。
要使这个工作你的模型必须与你的数据库表相同。我用 JPA 创建了我的模型。
希望这会有所帮助!
【讨论】:
【参考方案2】:我知道这是旧的,但我正在寻找有关 Apache Commons DBUtils QueryRunner 的信息并遇到了这个......为了将来参考,您可以:
先将ArrayList转成Object[][]:
Object[][] params = null;
params = listOfObjectArrays.toArray(params);
然后将params
传递给QueryRunner 上的批处理方法(返回int[]):
qr.batch("insert into MyTable (param1,param2,param3) values (?,?,?)", params);
【讨论】:
我也在为此苦苦挣扎。我有 List以上是关于使用 QueryRunner 插入 ArrayList<Object[]>的主要内容,如果未能解决你的问题,请参考以下文章