Java 中的数据映射器模式:解耦数据存储与业务逻辑
也称为
- 对象关系映射 (ORM)
数据映射器模式的意图
数据映射器模式旨在创建数据库和业务逻辑之间的抽象层,使它们能够独立发展。它将数据从数据库对象映射到内存中的数据结构,反之亦然,最大程度地减少了应用程序核心逻辑与底层数据库结构之间的直接依赖关系。这种解耦对于提高 Java 编程中的可维护性和灵活性至关重要。
数据映射器模式的详细解释及实际案例
实际案例
考虑一个图书馆系统,其中书籍存储在具有复杂关系和各种属性的数据库中,例如标题、作者、出版年份和类型。在这种情况下,可以使用数据映射器模式将书籍的数据库记录映射到应用程序中的内存对象。数据映射器将处理书籍对象的检索、存储和更新,允许应用程序的业务逻辑直接使用书籍对象,而无需关心底层数据库结构。这种分离使更改数据库模式变得更容易,而不会影响业务逻辑,反之亦然。
简单来说
一层映射器,在对象和数据库之间移动数据,同时保持它们彼此独立。
维基百科说
数据映射器是一种数据访问层,它在持久数据存储(通常是关系数据库)和内存中的数据表示(领域层)之间执行双向数据传输。该模式的目标是使内存中的表示和持久数据存储彼此独立,以及数据映射器本身。这在需要对领域层中的数据建模和强制实施严格的业务流程,而这些流程不能完全映射到持久数据存储时非常有用。
Java 中数据映射器模式的编程示例
数据映射器是一种设计模式,它将内存中的对象与数据库分离。它的职责是在两者之间传输数据,并将其彼此隔离。这种模式促进了单一职责原则和关注点分离.
在 data-mapper 模块中,该模式使用 Student
类和 StudentDataMapper
接口进行了演示。
Student
类是一个简单的 POJO(普通 Java 对象),代表一个学生。它具有诸如学生 ID、姓名和年级之类的属性。
public class Student {
private int studentId;
private String name;
private char grade;
// ...
}
StudentDataMapper
接口定义了可以在 Student
对象上执行的操作。这些操作包括 insert
、update
、delete
和 find
。
public interface StudentDataMapper {
void insert(final Student student);
void update(final Student student);
void delete(final Student student);
Optional<Student> find(final int studentId);
// ...
}
StudentDataMapperImpl
类实现了 StudentDataMapper
接口。它包含与数据库交互的实际逻辑。
public class StudentDataMapperImpl implements StudentDataMapper {
// ...
@Override
public void insert(final Student student) {
// Insert student into the database
}
@Override
public void update(final Student student) {
// Update student in the database
}
@Override
public void delete(final Student student) {
// Delete student from the database
}
@Override
public Optional<Student> find(final int studentId) {
// Find student in the database
}
// ...
}
App
类包含演示 StudentDataMapper
使用的主要方法。它创建了一个 Student
对象,将其插入数据库,找到它,更新它,最后删除它。
public class App {
public static void main(final String... args) {
final var mapper = new StudentDataMapperImpl();
var student = new Student(1, "Adam", 'A');
mapper.insert(student);
final var studentToBeFound = mapper.find(student.getStudentId());
student = new Student(student.getStudentId(), "AdamUpdated", 'A');
mapper.update(student);
mapper.delete(student);
}
}
程序输出
13:54:29.234 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=Adam, grade=A), is inserted
13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Optional[Student(studentId=1, name=Adam, grade=A)], is searched
13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is updated
13:54:29.238 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is going to be deleted
何时在 Java 中使用数据映射器模式
在以下任何情况下使用数据映射器
- 当需要将内存中的对象与数据库实体解耦,以促进单一职责原则和关注点分离.
- 在需要 ORM 工具来弥合面向对象模型和关系数据库之间差距的应用程序中。
- 在使用复杂数据库模式的情况下,直接数据操作和对象创建会导致代码笨拙且容易出错。
数据映射器模式 Java 教程
- Spring Boot RowMapper (ZetCode)
- Spring BeanPropertyRowMapper 教程 (ZetCode)
- Java 中的数据传输对象模式 - 实现和映射 (StackAbuse)
Java 中数据映射器模式的实际应用
- Java 中的 ORM 框架,例如 Hibernate。
- 企业应用程序中的数据访问层,其中业务逻辑和数据库管理保持分离。
- 需要数据库交互但不会将代码绑定到特定数据库实现的应用程序。
数据映射器模式的优缺点
优点
- 通过将持久化逻辑与业务逻辑分离,促进了单一职责原则.
- 通过集中数据交互逻辑,增强了可维护性和可读性。
- 提高了应用程序在数据库模式发生变化时适应的能力,只需对业务逻辑进行最小的更改。
权衡
- 通过额外的抽象层引入了复杂性。
- 由于抽象层的存在,可能会导致性能开销,尤其是在大型应用程序或复杂查询中。
- 要求开发人员除了学习和了解正在使用的数据库和 ORM 框架之外,还要学习和了解抽象层。
相关的 Java 设计模式
- Active Record:将数据访问逻辑和业务逻辑组合在领域实体本身中,这与数据映射器的关注点分离相反。
- 对象关系映射 (ORM):将面向对象编程语言数据映射到关系数据库的技术。
- Repository:提供数据层的抽象,充当内存中领域对象的集合。
- Unit of Work:管理事务并跟踪受业务事务影响的对象,以确保更改是一致的和事务性的。