Spring 新手,我正在尝试将
List<Map<String, Object>>
插入表中。到目前为止,我一直在使用 SqlParameterSource
进行批量更新,当向他们提供 java bean 时,它可以正常工作。像这样的东西:
@Autowired
private NamedParameterJDBCTemplate v2_template;
public int[] bulkInsertIntoSiteTable(List<SiteBean> list){
SqlParameterSource[] batch = SqlParameterSourceUtils
.createBatch(list.toArray());
int[] updateCounts = v2_template
.batchUpdate(
"insert into sitestatus (website, status, createdby) values (:website, :status, :username)",
batch);
return updateCounts;
}
但是,我尝试了相同的技术,用映射列表代替 bean,但失败了(没错)。
public int[] bulkInsertIntoSiteTable(List<Map<String, Object>> list){
SqlParameterSource[] batch = SqlParameterSourceUtils
.createBatch(list.toArray());
int[] updateCounts = v2_template
.batchUpdate(
"insert into sitestatus (website, status, createdby) values (:website, :status, :username)",
batch);
return updateCounts;
}
上述代码失败,但出现以下异常:
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: No value supplied for the SQL parameter 'website': Invalid property 'website' of bean class [org.springframework.util.LinkedCaseInsensitiveMap]: Bean property 'website' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.jdbc.core.namedparam.NamedParameterUtils.buildValueArray(NamedParameterUtils.java:322)
at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils$1.setValues(NamedParameterBatchUpdateUtils.java:45)
at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:893)
at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:1)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:615)
at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:884)
at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(NamedParameterBatchUpdateUtils.java:40)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:303)
at tester.utitlies.dao.VersionTwoDao.bulkInsertIntoSites(VersionTwoDao.java:21)
at tester.utitlies.runner.Main.main(Main.java:28)
我猜它失败了,因为它认为列表是一批豆子。我找不到在 Spring 中使用 地图列表 和使用
NamedParameterJDBCTemplate
执行批量更新的方法。请指教。
根据 Spring
NamedParameterJDBCTemplate
文档,在 here 找到,此方法可用于使用地图进行批量更新。
int[] batchUpdate(String sql, Map<String,?>[] batchValues)
真正的挑战是从相应的
Map<String, Object>
中获取 List<Map<String, Object>>
数组。我使用以下代码来获取数组并执行批量更新。
public static Map<String, Object>[] getArrayData(List<Map<String, Object>> list){
@SuppressWarnings("unchecked")
Map<String, Object>[] maps = new HashMap[list.size()];
Iterator<Map<String, Object>> iterator = list.iterator();
int i = 0;
while (iterator.hasNext()) {
Map<java.lang.String, java.lang.Object> map = (Map<java.lang.String, java.lang.Object>) iterator
.next();
maps[i++] = map;
}
return maps;
}
您不能直接在NamedParameterJdbcTemplate的batchUpdate中使用您的bean,NamedParameterJdbcTemplate的batchUpdate仅接受数组形式的参数。可以是 SqlParameterSource 数组,也可以是 Map 数组。
在这里我将演示如何使用 Map 数组来实现你的目标。
考虑到上面的问题,将你的Bean列表转换成map数组, 每个映射对应于要插入的一行或一个 Bean 对象,字段及其值以键值对的形式存储在映射内,其中键是字段名称,值是正在考虑的字段的值。
@Autowired
private NamedParameterJDBCTemplate v2_template;
public int[] bulkInsertIntoSiteTable(List<SiteBean> list){
String yourQuery = "insert into sitestatus (website, status, createdby)
values (:website, :status, :username)"
Map<String,Object>[] batchOfInputs = new HashMap[list.size()];
int count = 0;
for(SiteBean sb : list.size()){
Map<String,Object> map = new HashMap();
map.put("website",sb.getWebsite());
map.put("status",sb.getStatus());
map.put("username",sb.getUsername());
batchOfInputs[count++]= map;
}
int[] updateCounts = v2_template.batchUpdate(yourQuery,batchOfInputs);
return updateCounts;
}
还有另一种方法可以避免
@SuppressWarnings("unchecked")
。
public static final String INSERT_INTO = "INSERT INTO {0} ({1}) VALUES ({2})";
private NamedParameterJdbcTemplate template;
template.batchUpdate(insertQuery(rowMaps.get(0)), batchArgs(mapRows));
/**
* Create SQL instruction INSERT from Map record
*
* @return literal INSERT INTO [schema].[prefix][table_name] (column1, column2, column3, ...)
* VALUES (value1, value2, value3, ...);
*/
public String insertQuery(Map<String, String> rowMap) {
String schemaTable = Objects.isNull(getSchema()) ? table : getSchema() + "." + table;
String splittedColumns = String.join(",", rowMap.keySet());
String splittedValues = rowMap.keySet().stream()
.map(s -> ":" + s).collect(Collectors.joining(","));
return MessageFormat.format(INSERT_INTO, schemaTable, splittedColumns, splittedValues);
}
private MapSqlParameterSource[] batchArgs(List<Map<String, String>> mapRows) {
int size = mapRows.size();
MapSqlParameterSource[] batchArgs = new MapSqlParameterSource[size];
IntStream.range(0, size).forEach(i -> {
MapSqlParameterSource args = new MapSqlParameterSource(mapRows.get(i));
batchArgs[i] = args;
});
return batchArgs;
}
致以诚挚的问候
在您的语句中,如果列表或地图对象列表是单例,则 SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray()) 将不起作用。在这种情况下,以下选项将有用。
public int[] bulkInsertIntoSiteTable(List<Map<String, Object>> list){
Map<String, Object>[] maps = new HashMap[list.size()];
IntStream.range(0, list.size()).forEach(x -> maps[x] = new HashMap<>(list.get(x)));
int[] updateCounts = v2_template
.batchUpdate(
"insert into sitestatus (website, status, createdby) values (:website, :status, :username)",
maps);
return updateCounts;
}
一个工作片段:
public List builkInsert(String insert,List details) {
Map<String, Object>[] maps = new HashMap[details.size()];
Map<String, Object>[] batchValues = (Map<String, Object>[]) details.toArray(maps);
int[] response= namedParameterJdbcTemplate.batchUpdate(insert, batchValues);
return Arrays.asList(response);
}
我用代码测试过。
Map<String, Object>[] rs = new Map<String, Object>[1];
Map<String, Object> item1 = new HashMap<>();
item1.put("name", "Tien Nguyen");
item1.put("age", 35);
rs[0] = item1;
NamedParameterJdbcTemplate jdbc = new NamedParameterJdbcTemplate(datasource);
// datasource from JDBC.
jdbc.batchUpdate("call sp(:name, :age)", rs);
希望很容易知道。 谢谢