java之dao

admin 101 0
DAO(Data Access Object)是Java开发中用于封装数据访问层的核心模式,其核心目标是将业务逻辑与数据操作解耦,通过定义DAO接口规范数据库操作(如增删改查),由具体实现类(如JDBC、Hibernate、MyBatis等)执行SQL与数据库交互,隐藏底层细节,该模式提升代码复用性,便于切换数据源,同时增强系统可维护性与测试性,是分层架构中连接业务层与数据层的重要桥梁,确保数据操作逻辑独立且清晰。

Java DAO模式详解:从数据访问到架构解耦

在Java企业级开发中,数据访问层(Data Access Layer, DAL)是连接业务逻辑与数据库的核心桥梁,而DAO(Data Access Object,数据访问对象)模式作为数据访问层最经典的设计模式之一,以其"解耦关注点、提升可维护性"的核心思想,成为Java开发者必备的设计工具,本文将从DAO模式的概念出发,深入剖析其结构、实现方式及最佳实践,帮助读者掌握这一关键架构模式。

DAO模式:什么是数据访问对象?

DAO模式是一种结构设计模式,其核心目标是将数据访问逻辑与业务逻辑分离,在未使用DAO模式的应用中,业务逻辑层(Service层)常常直接依赖JDBC、Hibernate、MyBatis等数据访问技术,导致代码耦合度高:一旦数据库技术更换(如从MySQL切换到PostgreSQL),或数据访问方式调整(从JDBC切换到JPA),业务逻辑层代码需要大量修改,而DAO模式通过引入"数据访问对象"这一中间层,让业务逻辑层仅通过DAO接口操作数据,无需关心底层数据存储的具体实现。

DAO模式的核心思想

  • 关注点分离:业务逻辑层专注业务流程(如用户注册、订单计算),数据访问层专注数据操作(如SQL执行、结果集映射)。
  • 抽象与封装:通过接口定义数据操作标准(如增删改查),具体实现由DAO类完成,隐藏底层技术细节。
  • 可维护性与可扩展性:更换数据库、优化查询逻辑时,只需修改DAO实现类,无需触动业务代码。

DAO模式的核心组成部分

一个完整的DAO模式实现通常包含以下四个核心组件,它们协同工作,形成清晰的数据访问架构:

DAO接口(DAO Interface)

定义数据操作的抽象方法,是业务逻辑层与数据访问层的"契约",接口中仅声明操作行为,不包含具体实现。

示例

public interface UserDao {
    User findById(Long id);          // 根据ID查询用户
    void save(User user);            // 保存用户
    void update(User user);          // 更新用户信息
    void deleteById(Long id);        // 根据ID删除用户
    List<User> findAll();            // 查询所有用户
    List<User> findByUsername(String username); // 根据用户名查询
}

DAO实现类(DAO Implementation)

实现DAO接口,完成具体的数据访问逻辑,根据底层技术不同,可能是JDBC实现、MyBatis实现、Hibernate实现等。

示例(基于JDBC的实现)

public class UserDaoImpl implements UserDao {
    private final DataSource dataSource; // 使用DataSource而非直接Connection
    @Override
    public User findById(Long id) {
        String sql = "SELECT id, username, email FROM users WHERE id = ?";
        try (Connection connection = dataSource.getConnection();
             PreparedStatement stmt = connection.prepareStatement(sql)) {
            stmt.setLong(1, id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                User user = new User();
                user.setId(rs.getLong("id"));
                user.setUsername(rs.getString("username"));
                user.setEmail(rs.getString("email"));
                return user;
            }
        } catch (SQLException e) {
            throw new DataAccessException("查询用户失败", e);
        }
        return null;
    }
    @Override
    public void save(User user) {
        String sql = "INSERT INTO users (username, email) VALUES (?, ?)";
        try (Connection connection = dataSource.getConnection();
             PreparedStatement stmt = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            stmt.setString(1, user.getUsername());
            stmt.setString(2, user.getEmail());
            int affectedRows = stmt.executeUpdate();
            if (affectedRows == 0) {
                throw new SQLException("创建用户失败,没有行受到影响");
            }
            try (ResultSet generatedKeys = stmt.getGeneratedKeys()) {
                if (generatedKeys.next()) {
                    user.setId(generatedKeys.getLong(1));
                } else {
                    throw new SQLException("创建用户失败,ID未获取");
                }
            }
        } catch (SQLException e) {
            throw new DataAccessException("保存用户失败", e);
        }
    }
    // 其他方法实现...
}

实体类(Entity/Model)

与数据库表结构对应的Java对象,用于封装数据。users表对应User实体类:

public class User {
    private Long id;
    private String username;
    private String email;
    private LocalDateTime createdAt;
    // 构造方法
    public User() {}
    public User(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.createdAt = LocalDateTime.now();
    }
    // getter/setter方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
}

数据源/连接管理(DataSource/Connection Management)

负责数据库连接的获取与释放,通常通过连接池(如HikariCP、Druid)实现,避免频繁创建和销毁连接带来的性能损耗。

示例(HikariCP配置)

public class DataSourceManager {
    private static HikariDataSource dataSource;
    static {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC");
        config.setUsername("root");
        config.setPassword("password");
        config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(5);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        dataSource

标签: #DAO