Java中的DAO和Mapper设计模式

在Java开发中,数据访问层(Data Access Layer,DAL)负责与数据源进行交互。在这层中,DAO(Data Access Object)和Mapper是两种常用的设计模式。了解这两者的区别和使用方法,对于构建高效、可维护的系统至关重要。

DAO(数据访问对象)

DAO是一种设计模式,旨在将数据访问逻辑与业务逻辑分离,使得数据操作更加独立和灵活。DAO通常提供了一组用于操作持久化对象的方法,开发人员可以通过DAO来调用底层数据库操作,而无需关心具体的实现。

DAO的基本结构

一个DAO通常包含基本的 CRUD(创建、读取、更新、删除)方法。以下是一个简单的用户DAO接口示例:

public interface UserDAO {
    void save(User user);
    User findById(int id);
    List<User> findAll();
    void update(User user);
    void delete(int id);
}

接下来,我们来实现这个接口。假设我们使用JDBC与MySQL数据库进行交互:

public class UserDAOImpl implements UserDAO {
    private Connection connection;

    public UserDAOImpl(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void save(User user) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, user.getName());
            statement.setString(2, user.getEmail());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public User findById(int id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        User user = null;
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setInt(1, id);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                user = new User(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("email"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }

    @Override
    public List<User> findAll() {
        List<User> users = new ArrayList<>();
        String sql = "SELECT * FROM users";
        try (Statement statement = connection.createStatement()) {
            ResultSet resultSet = statement.executeQuery(sql);
            while (resultSet.next()) {
                User user = new User(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("email"));
                users.add(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return users;
    }

    @Override
    public void update(User user) {
        String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, user.getName());
            statement.setString(2, user.getEmail());
            statement.setInt(3, user.getId());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void delete(int id) {
        String sql = "DELETE FROM users WHERE id = ?";
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setInt(1, id);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Mapper(映射器)

Mapper是一个广泛使用的概念,特别是在ORM(对象关系映射)框架中。与DAO不同,Mapper通常用于更复杂的查询和关系映射,尤其是在与数据库表的映射和复杂SQL操作方面。

Mapper的基本结构

在使用MyBatis这样一个流行的ORM框架时,Mapper通常涉及XML或注解配置来定义SQL。以下是一个使用注解的UserMapper示例:

@Mapper
public interface UserMapper {
    @Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
    void save(User user);

    @Select("SELECT * FROM users WHERE id = #{id}")
    User findById(int id);

    @Select("SELECT * FROM users")
    List<User> findAll();

    @Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")
    void update(User user);

    @Delete("DELETE FROM users WHERE id = #{id}")
    void delete(int id);
}

DAO与Mapper的比较

特性 DAO Mapper
目的 处理数据操作逻辑 映射SQL到对象
适用场景 适合简单的CRUD操作 适合复杂查询与映射
实现方式 依赖JDBC或JPA等技术 通常依赖框架如MyBatis、Hibernate等
复杂性 较低 较高(尤其是涉及复杂SQL时)

使用示例

接下来,我们可以通过以下简单的序列图来展示使用DAO和Mapper的步骤。

sequenceDiagram
    participant C as Client
    participant D as UserDAO
    participant M as UserMapper
    participant DB as Database

    C->>+D: save(user)
    D->>DB: INSERT INTO users VALUES (user)
    DB->>D: success
    D->>-C: User saved

    C->>+M: findById(id)
    M->>DB: SELECT * FROM users WHERE id = id
    DB->>M: User data
    M->>-C: User object

结论

DAO和Mapper都是Java应用开发中重要的设计模式,各有特点和使用场景。DAO提供了一个简单而清晰的接口,用于访问底层数据源,适合于基本的CRUD操作。Mapper则提供了更高层次的抽象,适合用于复杂的SQL查询和对象关系映射。

在选择使用DAO还是Mapper时,可以根据项目的复杂性、团队的技术栈和开发需求来决定。通过合理的架构设计和使用这些设计模式,能够大大提高系统的可维护性和扩展性。