1. Java-SQL操作全解析:从基础到实战技巧
作为一名长期奋战在一线的Java开发者,我深刻理解SQL操作在业务系统中的核心地位。今天我想系统梳理Java中各类SQL操作的关键技术与实战心得,涵盖数据插入、查询、过滤、排序等基础操作,以及返回行数限制、模糊查询、数据合并等进阶技巧。这些内容都是我多年踩坑后总结的硬核经验,尤其适合需要快速提升数据库操作能力的初中级开发者。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础CRUD操作精要
2.1 数据插入的三种范式
在Java中执行INSERT操作时,PreparedStatement是绝对的首选方案。来看一个用户数据插入的典型示例:
java复制String sql = "INSERT INTO users (username, email, created_at) VALUES (?, ?, ?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setString(1, "dev_zhang");
pstmt.setString(2, "dev@example.com");
pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
int affectedRows = pstmt.executeUpdate();
System.out.println("插入记录数: " + affectedRows);
}
关键提示:永远使用PreparedStatement而非Statement,这不仅能防止SQL注入,还能提升批量操作的性能。
批量插入时,记得关闭自动提交并合理设置batchSize:
java复制connection.setAutoCommit(false);
String sql = "INSERT INTO products (name, price) VALUES (?, ?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
for (Product product : productList) {
pstmt.setString(1, product.getName());
pstmt.setBigDecimal(2, product.getPrice());
pstmt.addBatch();
if (i % 1000 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch();
connection.commit();
}
2.2 数据查询的艺术
基础查询看似简单,但优化空间巨大。先看一个典型反例:
java复制// 错误示范:直接拼接SQL
String sql = "SELECT * FROM orders WHERE user_id = " + userId;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
正确做法应该这样:
java复制String sql = "SELECT order_id, total_amount, status FROM orders WHERE user_id = ?";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
// 处理结果集
}
}
经验之谈:务必明确指定查询字段而非使用SELECT *,这能减少网络传输量并提高查询效率。
3. 高级查询技巧实战
3.1 分页查询的工业级实现
分页查询是业务系统的高频操作,以下是经过生产验证的实现方案:
java复制public List<Order> getOrdersByPage(int userId, int pageNum, int pageSize) {
String sql = "SELECT order_id, total_amount, status " +
"FROM orders " +
"WHERE user_id = ? " +
"ORDER BY created_at DESC " +
"LIMIT ? OFFSET ?";
int offset = (pageNum - 1) * pageSize;
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, userId);
pstmt.setInt(2, pageSize);
pstmt.setInt(3, offset);
ResultSet rs = pstmt.executeQuery();
List<Order> orders = new ArrayList<>();
while (rs.next()) {
orders.add(mapRowToOrder(rs));
}
return orders;
}
}
对于百万级数据的分页,建议使用"游标分页"替代传统LIMIT分页:
java复制// 基于最后一条记录的ID进行分页
String sql = "SELECT id, name FROM products " +
"WHERE id > ? " +
"ORDER BY id " +
"LIMIT ?";
3.2 模糊查询的性能优化
LIKE查询是性能杀手,但通过以下技巧可以显著改善:
java复制// 前缀匹配可以利用索引
String sql = "SELECT * FROM articles WHERE title LIKE 'Java%'";
// 包含匹配的优化方案
String sql = "SELECT * FROM articles WHERE title LIKE '%设计模式%'";
// 应该考虑使用全文索引或专门的搜索引擎
对于中文模糊查询,建议添加拼音字段并建立索引:
sql复制ALTER TABLE products ADD COLUMN name_pinyin VARCHAR(255);
CREATE INDEX idx_product_pinyin ON products(name_pinyin);
Java端处理:
java复制public List<Product> searchProducts(String keyword) {
String pinyin = PinyinUtils.toPinyin(keyword);
String sql = "SELECT * FROM products " +
"WHERE name LIKE ? OR name_pinyin LIKE ?";
// ...执行查询
}
4. 数据操作进阶技巧
4.1 事务处理的最佳实践
数据库事务是保证数据一致性的关键,来看一个电商下单的典型场景:
java复制public boolean placeOrder(Order order, List<OrderItem> items) {
Connection conn = null;
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false);
// 1. 插入订单主表
insertOrder(conn, order);
// 2. 扣减库存
for (OrderItem item : items) {
reduceInventory(conn, item.getProductId(), item.getQuantity());
}
// 3. 记录操作日志
logOrderOperation(conn, order.getOrderId(), "CREATE");
conn.commit();
return true;
} catch (SQLException e) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
logger.error("回滚失败", ex);
}
}
return false;
} finally {
if (conn != null) {
try {
conn.setAutoCommit(true);
conn.close();
} catch (SQLException e) {
logger.error("连接关闭异常", e);
}
}
}
}
血泪教训:事务中不要包含远程调用、长时间等待等非数据库操作,这会导致连接长时间占用,引发连接池耗尽。
4.2 批量更新的性能优化
批量更新数据时,这些技巧可以提升10倍以上性能:
java复制// 方案1
