好的,我将根据规划,撰写Java技术专家面试专题系列的第五篇:“数据库与持久化”。这篇文章将深入探讨Java与数据库交互的核心技术,包括JDBC、ORM框架、SQL优化以及分布式事务等,结合代码示例和面试问题,帮助读者掌握持久化层的原理和实践,为技术专家面试提供全面支持。以下是完整内容:
数据库与持久化是Java企业级开发的关键环节,涉及数据存储、访问和一致性保障。本篇将从JDBC基础、ORM框架(如MyBatis和Hibernate)、SQL优化到分布式事务,系统讲解Java持久化技术,助你在面试中展现数据库设计与优化的能力。
JDBC(Java Database Connectivity)是Java访问关系型数据库的基础。
核心组件
DriverManager
: 加载数据库驱动。Connection
: 数据库连接。Statement
/PreparedStatement
: 执行SQL。ResultSet
: 查询结果。
连接池
- 提高连接复用效率,常见实现:HikariCP(高性能)、Druid(监控功能强)。
示例: 使用HikariCP连接数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCDemo {
public static void main(String[] args) throws Exception {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(10);
try (HikariDataSource ds = new HikariDataSource(config);
Connection conn = ds.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?")) {
stmt.setInt(1, 1);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println("User: " + rs.getString("name"));
}
}
}
}
|
面试问题:
- 问题: 为什么使用连接池?
- 答案: 直接创建连接开销大(TCP握手、认证),连接池复用连接,减少资源消耗,提高性能。
ORM(Object-Relational Mapping)将对象映射到数据库表。
MyBatis
- 半自动映射,SQL由开发者编写。
- 优点:灵活,易优化。
- 缺点:SQL维护成本高。
Hibernate
- 全自动映射,生成SQL。
- 优点:开发效率高,支持复杂关系。
- 缺点:SQL控制少,性能调优复杂。
示例: MyBatis简单查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // UserMapper.java
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUser(int id);
}
// User.java
public class User {
private int id;
private String name;
// getters and setters
}
// Main.java
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.io.Resources;
public class MyBatisDemo {
public static void main(String[] args) throws Exception {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
try (SqlSession session = factory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUser(1);
System.out.println("User: " + user.getName());
}
}
}
|
面试问题:
- 问题: MyBatis的
#{}
和${}
有什么区别? - 答案:
#{}
是预编译参数,防SQL注入;${}
是字符串替换,易引发注入风险。
高效的SQL是数据库性能的关键。
索引设计
- 单列索引、复合索引、主键索引。
- 覆盖索引:查询字段都在索引中,避免回表。
执行计划分析
优化实践
- 避免
SELECT *
,指定字段。 - 用
JOIN
替代子查询。
示例: 索引优化
1
2
3
4
5
| -- 创建索引
CREATE INDEX idx_name ON users(name);
-- 优化查询
EXPLAIN SELECT name FROM users WHERE name = 'Alice';
|
面试问题:
- 问题: 如何设计高并发订单表的索引?
- 答案: 根据查询条件(如订单号、用户ID),创建复合索引(如
INDEX(order_id, user_id)
),确保覆盖高频字段。
分布式系统下,事务一致性是挑战。
XA事务
- 基于两阶段提交(2PC),强一致性。
- 缺点:性能低,锁资源时间长。
TCC(Try-Confirm-Cancel)
- 业务补偿机制,柔性事务。
- 优点:高性能,适合微服务。
示例: TCC伪代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public class OrderService {
public void createOrder(Order order) {
try {
// Try阶段:预留资源
inventoryService.reserve(order.getItemId(), order.getQuantity());
paymentService.reserve(order.getUserId(), order.getAmount());
// Confirm阶段:提交
inventoryService.confirm(order.getItemId());
paymentService.confirm(order.getUserId());
} catch (Exception e) {
// Cancel阶段:回滚
inventoryService.cancel(order.getItemId());
paymentService.cancel(order.getUserId());
throw e;
}
}
}
|
面试问题:
- 问题: XA和TCC的区别是什么?
- 答案: XA是全局事务,依赖数据库支持2PC,强一致性但性能差;TCC是业务补偿,异步执行,高可用但实现复杂。
NoSQL数据库(如Redis、MongoDB)在高并发场景中广泛应用。
示例: Redis分布式锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| import redis.clients.jedis.Jedis;
public class RedisLockDemo {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("localhost", 6379)) {
String lockKey = "lock:resource";
// 获取锁
if ("OK".equals(jedis.set(lockKey, "1", "NX", "PX", 10000))) {
System.out.println("Lock acquired");
// 业务逻辑
Thread.sleep(1000);
jedis.del(lockKey); // 释放锁
System.out.println("Lock released");
} else {
System.out.println("Failed to acquire lock");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
面试问题:
- 问题: Redis分布式锁的优缺点?
- 答案: 优点是高性能、简单;缺点是锁超时可能导致并发问题,需设置合理过期时间或续期。
- 实践: 配置MyBatis项目,优化SQL。
- 深入: 阅读Hibernate源码,理解懒加载。
- 表达: 用案例解释分布式事务的选择。
数据库与持久化是Java开发的基石,掌握JDBC、ORM和分布式事务,能让你在面试中展现全面的技术能力。下一专题将探讨微服务与分布式系统,敬请期待!