解决有序数据中插入不确定数据保证数据插入的位置顺序正确排序
前言
java 数据库中存储自增id 有序的数据, 前端页面基于 id 5和 6 之间新增一条数据,在 id 6 和 7之间新增 2条,或者更复杂的场景,后台接口如何保存数据使得页面数据显示的顺序就是前端新增的数据的位置
思路
在面对需要在特定位置插入多条数据的情况时,手动调整自增ID的方式变得复杂且容易出错,尤其是当并发操作发生时。因此,推荐的做法是在数据库表中添加一个额外的字段来维护数据的显示顺序。
让我们假设我们有一个名为 display_order 的字段,该字段用来表示记录在前端的显示顺序。你可以按照以下步骤来实现需求:
为表添加一个 display_order 字段(如果还没有的话),类型可以是整数或者浮点数。
当插入新记录时,而不是改变自增ID,你只需要将新记录的 display_order 设定为合适的值。
在有多条记录同时插入的情况下,你需要计算每条新记录的 display_order 值,这通常是现有记录的 display_order 值的平均值。
下面是一个简化的例子来说明这个过程:
首先,假设立刻的数据库状态如下:
要在ID 5和6之间插入一条新数据,你可以设置新行的 display_order 为 (5 + 6) / 2 = 5.5,然后对表中ID大于等于5的行进行更新,使它们的 display_order 加1。
对于在ID 6和7之间插入两条新数据,你可以设置第一条新行的 display_order 为 (6 + 7) / 2 = 6.5,第二条新行的 display_order 为 (6.5 + 7) / 2 = 6.75,然后同样更新这些ID后的行的 display_order。
以下是如何在Java后端实现它的伪代码:
public void insertRecords(List<RecordToInsert> recordsToInsert, Connection conn) throws SQLException {conn.setAutoCommit(false); // Start transactiontry {for (RecordToInsert record : recordsToInsert) {// Calculate the display order for each new recorddouble displayOrder = calculateDisplayOrder(record.getInsertAfterId(), conn);// Insert the new record with the calculated display orderinsertRecordWithDisplayOrder(displayOrder, record.getData(), conn);// Update the display order of subsequent recordsupdateSubsequentDisplayOrders(displayOrder, conn);}conn.commit(); // Commit transaction} catch (SQLException e) {conn.rollback(); // Rollback on errorthrow e;} finally {conn.close();}
}private double calculateDisplayOrder(int insertAfterId, Connection conn) throws SQLException {// Fetch the display order of the record after which we want to insert the new one// Adjust the calculation based on whether you are inserting before or after// Add logic to handle cases where multiple records are inserted between the same two IDs// ...return calculatedDisplayOrder;
}private void insertRecordWithDisplayOrder(double displayOrder, String data, Connection conn) throws SQLException {String sql = "INSERT INTO your_table (display_order, data) VALUES (?, ?)";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setDouble(1, displayOrder);stmt.setString(2, data);stmt.executeUpdate();}
}private void updateSubsequentDisplayOrders(double newDisplayOrder, Connection conn) throws SQLException {String sql = "UPDATE your_table SET display_order = display_order + ? WHERE display_order >= ?";try (PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setDouble(1, INSERT_STEP); // Define INSERT_STEP based on how you want to space out your display ordersstmt.setDouble(2, newDisplayOrder);stmt.executeUpdate();}
}
注意:上述代码仅作为示例,实际的实现会更复杂,特别是考虑到并发性和性能优化。例如,你可能需要一个锁机制来防止多个用户同时更改同一范围内的 display_order。此外,还需要考虑当大量的插入发生在相近的位置时可能导致精度问题。解决这些问题可能需要进一步的策略,比如重新排序整个列表或者使用不同的数据结构。