DEV Community

Jihao Deng
Jihao Deng

Posted on

DA03 Data source Layer

本篇主要讲数据层(Data source Layer),它有以下四个pattern:

  • Table Data Gateway
  • Row Data Gateway
  • Active Record
  • Mapper

Data source Layer的作用

为了让内存中运行的程序与数据库进行交互,其中一种方式是将SQL以字符串的方式存在程序中,再将它发送到数据库里,这样做会有很多问题:

  • 高耦合;
  • Developer需要同时掌握编写Domain Layer的语言和SQL语言;
  • 数据库也将以字符串的方式返回查询结果,这种结果需要进行处理,而这些事情并不该在Domain Layer中做。

为了解决这些问题,现在有四种pattern。

Table Data Gateway

An object that acts as a gateway to a database table. One instance handles all the rows in the table.

一个对象封装了对一个数据库表的访问

public class StudentGateway {
    public ResultSet findAll() {...}

    public ResultSet findById(int id) {...}

    public void addStudent(String firstName, String surname, ...) {...}

    public void deleteStudent(int id) {...}

    public void updateStudent(int id, String firstName, String surname, ...) {...}

    public ResultSet findBySurname(String surname) {...}
    ...
}
Enter fullscreen mode Exit fullscreen mode

Table Data Gateway的优缺点

Pros

  • 简单明了
  • 兼容Table Module

Cons

  • 与Domain Model不兼容,因为它不希望把对一张表的所有操作糅合在一起
  • Bad scalability,如果表改变,那么Gateway就需要做改变;如果有很多张表,那么也需要管理大量的Gateways

Row Data Gateway

An object that acts as a gateway to a single record in a data source.

一条记录对应一个对象

public class Student {
    private int id;
    private String firstName;
    private String surname;

    // getters and setters

    public void addStudent(String firstName, String surname, ...) {...}
    public void deleteStudent() {...}
    public void updateStudent(String firstName, String surname, ...) {...}

}
Enter fullscreen mode Exit fullscreen mode

对于查询操作,需要额外编写一个Finder类:

class StudentFinder {
    public List<Student> findAll() {...}
    public Student findById(int id) {...}
}
Enter fullscreen mode Exit fullscreen mode

Row Data Gateway的优缺点

Pros

  • 简单明了
  • 兼容Transaction Script

Cons

  • 与Domain Model不兼容
  • 修改数据库表需要同时修改大量代码

Active Record

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.

与Row Data Gateway不同的是,Active Record的对象里还额外包含了domain logic方法。

public class Student {
    private int id;
    private String firstName;
    private String surname;

    // getters and setters

    public void addStudent(String firstName, String surname, ...) {...}
    public void deleteStudent() {...}
    public void updateStudent(String firstName, String surname, ...) {...}

    // the following methods implements domain logic
    public void getExemption() {...}
    public void addDependency() {...}
}
Enter fullscreen mode Exit fullscreen mode

与Row Data Gateway相同,对于查询操作,需要额外编写一个Finder类,或者在类中添加static finder方法。

Active Record的优缺点

Pros

  • High cohesion: 高内聚,因为将逻辑方法与一条记录放在了一个类中
  • 与transaction script兼容

Cons

  • 可重用性差
  • 修改数据库表需要同时修改大量代码

Data Mapper

A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.

该pattern意在降低对象与数据库的依赖,mapper相当于一个个连接内存中的对象和数据库表的桥梁。

With Data Mapper the in-memory objects needn't know even that there's a database present; they need no SQL interface code, and certainly no knowledge of the database schema.

public class Student {
    private int id;
    private String firstName;
    private String surname;

    // getters and setters

    // the following methods implements domain logic
    public void getExemption() {...}
    public void addDependency() {...}
}

public class StudentMapper {
    public static List<Student> findAll() {...}
    public static Student findStudentById(int id) {...}
    public static void addStudent(String firstName, String surname, ...) {...}
    public static void deleteStudent() {...}
    public static void updateStudent(String firstName, String surname, ...) {...}
}
Enter fullscreen mode Exit fullscreen mode

Data Mapper的优缺点

Pros

  • 低耦合
  • 适合Domain Model,domain layer的代码以及数据库的可重用性高

Cons

  • 复杂,额外添加了一层layer,只适合在domain logic非常复杂的情况下使用(但实际上,我们一直都在用这种pattern写web项目)

选择合适的数据层pattern

  • Table data gateway: the domain is simple, and uses the table module pattern;
  • Row data gateway: the domain is simple, and uses the transcript script pattern and design-time type safety is desired. It should not be used if there is a high likelihood of the database schema changing.
  • Active Record: the domain logic is somewhat complicated. It should not be used if there is a high likelihood of the database schema changing.
  • Data Mapper: the domain logic is particularly complex, and should be used in conjunction with the domain model pattern. It should also be used if there is a good chance that either the data source layer is likely to change, or if the domain logic is likely to change without a change to the underlying data.

Top comments (0)