Java技术专家面试专题系列(五):数据库与持久化

好的,我将根据规划,撰写Java技术专家面试专题系列的第五篇:“数据库与持久化”。这篇文章将深入探讨Java与数据库交互的核心技术,包括JDBC、ORM框架、SQL优化以及分布式事务等,结合代码示例和面试问题,帮助读者掌握持久化层的原理和实践,为技术专家面试提供全面支持。以下是完整内容:


Java技术专家面试专题系列(五):数据库与持久化

数据库与持久化是Java企业级开发的关键环节,涉及数据存储、访问和一致性保障。本篇将从JDBC基础、ORM框架(如MyBatis和Hibernate)、SQL优化到分布式事务,系统讲解Java持久化技术,助你在面试中展现数据库设计与优化的能力。

1. JDBC基础与连接池

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握手、认证),连接池复用连接,减少资源消耗,提高性能。

2. ORM框架对比:MyBatis vs Hibernate

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注入;${}是字符串替换,易引发注入风险。

3. SQL优化技巧

高效的SQL是数据库性能的关键。

  • 索引设计

    • 单列索引、复合索引、主键索引。
    • 覆盖索引:查询字段都在索引中,避免回表。
  • 执行计划分析

    • 使用EXPLAIN查看查询路径。
  • 优化实践

    • 避免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)),确保覆盖高频字段。

4. 分布式事务解决方案

分布式系统下,事务一致性是挑战。

  • 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是业务补偿,异步执行,高可用但实现复杂。

5. NoSQL集成

NoSQL数据库(如Redis、MongoDB)在高并发场景中广泛应用。

  • 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分布式锁的优缺点?
  • 答案: 优点是高性能、简单;缺点是锁超时可能导致并发问题,需设置合理过期时间或续期。

6. 学习与面试建议

  • 实践: 配置MyBatis项目,优化SQL。
  • 深入: 阅读Hibernate源码,理解懒加载。
  • 表达: 用案例解释分布式事务的选择。

结语

数据库与持久化是Java开发的基石,掌握JDBC、ORM和分布式事务,能让你在面试中展现全面的技术能力。下一专题将探讨微服务与分布式系统,敬请期待!

updatedupdated2025-03-312025-03-31