DA03 Data source Layer
Jihao Deng
Posted on August 19, 2020
本篇主要讲数据层(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) {...}
...
}
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, ...) {...}
}
对于查询操作,需要额外编写一个Finder
类:
class StudentFinder {
public List<Student> findAll() {...}
public Student findById(int id) {...}
}
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() {...}
}
与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, ...) {...}
}
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.
Posted on August 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.