使用Spring jdbcTemplate的insertOrUpdate操作的最佳实践是什么?

时间:2014-04-08 15:36:06

标签: java spring jdbctemplate

假设我们有一个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)来完成这个操作。

1 个答案:

答案 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();
            }
        });

    }

}