樂觀鎖機制是一種并發控制策略,適用于讀操作遠多于寫操作的場景。在Java中,樂觀鎖主要通過版本號或時間戳來實現。下面是一個簡單的示例,展示如何使用Java樂觀鎖機制:
Product
),并為其添加一個版本號字段(例如version
):public class Product {
private Long id;
private String name;
private Integer price;
private Integer version; // 添加版本號字段
// 省略getter和setter方法
}
ProductDao
),使用SELECT ... FOR UPDATE
語句查詢數據,并使用version
字段進行樂觀鎖控制:public class ProductDao {
private JdbcTemplate jdbcTemplate;
public Product findProductByIdForUpdate(Long id) {
String sql = "SELECT * FROM products WHERE id = ? FOR UPDATE";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, (resultSet, rowNum) -> {
Product product = new Product();
product.setId(resultSet.getLong("id"));
product.setName(resultSet.getString("name"));
product.setPrice(resultSet.getInt("price"));
product.setVersion(resultSet.getInt("version"));
return product;
});
}
public int updateProduct(Product product) {
String sql = "UPDATE products SET name = ?, price = ?, version = version + 1 WHERE id = ? AND version = ?";
int updatedRows = jdbcTemplate.update(sql, product.getName(), product.getPrice(), product.getId(), product.getVersion());
return updatedRows;
}
}
在這個示例中,findProductByIdForUpdate
方法使用SELECT ... FOR UPDATE
語句查詢數據,并將version
字段鎖定,以防止其他事務修改數據。updateProduct
方法在更新數據時,會檢查version
字段是否與數據庫中的版本號一致,如果一致則更新數據并遞增版本號,否則更新失敗。
ProductService
),調用findProductByIdForUpdate
方法獲取數據,并在更新數據時調用updateProduct
方法:public class ProductService {
private ProductDao productDao;
public Product updateProduct(Long id, String newName, Integer newPrice) {
Product product = productDao.findProductByIdForUpdate(id);
if (product != null) {
product.setName(newName);
product.setPrice(newPrice);
int updatedRows = productDao.updateProduct(product);
if (updatedRows > 0) {
return product;
} else {
// 版本號不一致,說明有其他事務修改了數據,需要重新嘗試操作或拋出異常
throw new OptimisticLockException("產品已被其他用戶修改");
}
} else {
// 未找到產品,需要重新嘗試操作或拋出異常
throw new EntityNotFoundException("產品不存在");
}
}
}
在這個示例中,updateProduct
方法首先調用findProductByIdForUpdate
方法獲取數據,然后更新數據并檢查版本號是否一致。如果版本號不一致,說明有其他事務修改了數據,需要重新嘗試操作或拋出異常。