假设我们有一个REST服务,接受来自经理的销售订单清单。 (我们知道managerId,他发送的所有订单都是一样的)
class SalesOrder {
String id;
String managerId;
//some other data
}
这项服务必须:
if SalesOrder not exists - save object
if object exists - update it
使用Spring jdbcTemplate saveOrUpdate这个列表的最有效方法(使用db方面)是什么?
我想到的第一种方法是:
public void saveOrUpdate(Iterable<SalesOrder> orders, String managerId) {
Set<String> presentInDbOrderIds = findOrderIds(managerId);
List<SalesOrder> ordersToInsert = new ArrayList<>();
List<SalesOrder> ordersToUpdate = new ArrayList<>();
for (SalesOrder ord : orders) {
if(presentInDbRecOrderHeaderIds.contains(ord.getId())) {
ordersToUpdate.add(ord);
} else {
ordersToInsert.add(ord);
}
}
batchInsertOrders(recOrdersToInsert);
batchUpdateOrders(recOrdersToUpdate);
}
第二个:
public void saveOrUpdate(Iterable<SalesOrder> orders) {
for (SalesOrder ord : orders) {
if(!update(ord)) { // returns true if object was updated
save(ord);
}
}
}
实际上(在我的情况下)每个订单都有一个orderLines的集合,它必须经过相同的过程,所以我正在寻找最简单的方法(到DB)来完成这个操作。
答案 0 :(得分:2)
取得所有权以检查是否需要检查或更新不是一个好主意。如果在准备好findOrderIds()之后另一个线程在DB中修改了数据怎么办...等等我不知道你是否已经实现了synchronized。
另外,如果为整个过程添加synchronized,则会添加额外的块。 DB处理更好的同步和索引数据。
我会用批量准备的陈述来做这样的事情:
class SalesOrder {
String id;
String managerId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getManagerId() {
return managerId;
}
public void setManagerId(String managerId) {
this.managerId = managerId;
}
}
public void saveOrUpdate(List<SalesOrder> orders, String managerId) {
String example_query = "insert into table(id, managerID,col2) values (?,?,?) on duplicate key update managerID= ? , col2 =?";
final int batchSize = 500;
for (int j = 0; j < orders.size(); j += batchSize) {
final List<SalesOrder> pickedOrders = orders.subList(j,
j + batchSize > orders.size() ? orders.size() : j + batchSize);
getJdbcTemplate().batchUpdate(example_query, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
SalesOrder order = pickedOrders.get(i);
ps.setString(1, order.getId());
ps.setString(2, order.getManagerId());
// so on
}
@Override
public int getBatchSize() {
return pickedOrders.size();
}
});
}
}