|
7 | 7 | ---
|
8 | 8 |
|
9 | 9 | ## Intent
|
10 |
| -A layer of mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself |
| 10 | +>Data Mapper is the software layer that separates the in-memory objects from the database. |
| 11 | +>Its responsibility is to transfer data between the objects and database and isolate them from each other. |
| 12 | +>If we obtain a Data Mapper, it is not necessary for the in-memory object to know if the database exists or not. |
| 13 | +>The user could directly manipulate the objects via Java command without having knowledge of SQL or database. |
| 14 | +
|
| 15 | +## Explanation |
| 16 | + |
| 17 | +Real world example |
| 18 | +>When a user accesses a specific web page through a browser, he only needs to do several operations to the browser. |
| 19 | +> The browser and the server will take the responsibility of saving data separately. |
| 20 | +> You don't need to know the existence of the server or how to operate the server. |
| 21 | +
|
| 22 | +In plain words |
| 23 | +>A layer of mappers that moves data between objects and a database while keeping them independent of each other. |
| 24 | +
|
| 25 | +Wikipedia says |
| 26 | +>A Data Mapper is a Data Access Layer that performs bidirectional transfer of data between a persistent data store |
| 27 | +> (often a relational database) and an in-memory data representation (the domain layer). The goal of the pattern is to |
| 28 | +> keep the in-memory representation and the persistent data store independent of each other and the data mapper itself. |
| 29 | +> This is useful when one needs to model and enforce strict business processes on the data in the domain layer that do |
| 30 | +> not map neatly to the persistent data store. |
| 31 | +
|
| 32 | +**Programmatic Example** |
| 33 | + |
| 34 | +>We have the student class to defining Students' attributes includes studentId, name and grade. |
| 35 | +>We have an interface of StudentDataMapper to lists out the possible behaviour for all possible student mappers. |
| 36 | +>And StudentDataMapperImpl class for the implementation of actions on Students Data. |
| 37 | +
|
| 38 | +```java |
| 39 | + |
| 40 | +public final class Student implements Serializable { |
| 41 | + |
| 42 | + private static final long serialVersionUID = 1L; |
| 43 | + |
| 44 | + @EqualsAndHashCode.Include |
| 45 | + private int studentId; |
| 46 | + private String name; |
| 47 | + private char grade; |
| 48 | + |
| 49 | + |
| 50 | + public interface StudentDataMapper { |
| 51 | + |
| 52 | + Optional<Student> find(int studentId); |
| 53 | + |
| 54 | + void insert(Student student) throws DataMapperException; |
| 55 | + |
| 56 | + void update(Student student) throws DataMapperException; |
| 57 | + |
| 58 | + void delete(Student student) throws DataMapperException; |
| 59 | + } |
| 60 | + |
| 61 | + public final class StudentDataMapperImpl implements StudentDataMapper { |
| 62 | + @Override |
| 63 | + public Optional<Student> find(int studentId) { |
| 64 | + return this.getStudents().stream().filter(x -> x.getStudentId() == studentId).findFirst(); |
| 65 | + } |
| 66 | + |
| 67 | + @Override |
| 68 | + public void update(Student studentToBeUpdated) throws DataMapperException { |
| 69 | + String name = studentToBeUpdated.getName(); |
| 70 | + Integer index = Optional.of(studentToBeUpdated) |
| 71 | + .map(Student::getStudentId) |
| 72 | + .flatMap(this::find) |
| 73 | + .map(students::indexOf) |
| 74 | + .orElseThrow(() -> new DataMapperException("Student [" + name + "] is not found")); |
| 75 | + students.set(index, studentToBeUpdated); |
| 76 | + } |
| 77 | + |
| 78 | + @Override |
| 79 | + public void insert(Student studentToBeInserted) throws DataMapperException { |
| 80 | + Optional<Student> student = find(studentToBeInserted.getStudentId()); |
| 81 | + if (student.isPresent()) { |
| 82 | + String name = studentToBeInserted.getName(); |
| 83 | + throw new DataMapperException("Student already [" + name + "] exists"); |
| 84 | + } |
| 85 | + |
| 86 | + students.add(studentToBeInserted); |
| 87 | + } |
| 88 | + |
| 89 | + @Override |
| 90 | + public void delete(Student studentToBeDeleted) throws DataMapperException { |
| 91 | + if (!students.remove(studentToBeDeleted)) { |
| 92 | + String name = studentToBeDeleted.getName(); |
| 93 | + throw new DataMapperException("Student [" + name + "] is not found"); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + public List<Student> getStudents() { |
| 98 | + return this.students; |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +``` |
| 104 | + |
| 105 | +>The below example demonstrates basic CRUD operations: Create, Read, Update, and Delete between the in-memory objects |
| 106 | +> and the database. |
| 107 | +
|
| 108 | +```java |
| 109 | +@Slf4j |
| 110 | +public final class App { |
| 111 | + |
| 112 | + private static final String STUDENT_STRING = "App.main(), student : "; |
| 113 | + |
| 114 | + public static void main(final String... args) { |
| 115 | + |
| 116 | + final var mapper = new StudentDataMapperImpl(); |
| 117 | + |
| 118 | + var student = new Student(1, "Adam", 'A'); |
| 119 | + |
| 120 | + mapper.insert(student); |
| 121 | + |
| 122 | + LOGGER.debug(STUDENT_STRING + student + ", is inserted"); |
| 123 | + |
| 124 | + final var studentToBeFound = mapper.find(student.getStudentId()); |
| 125 | + |
| 126 | + LOGGER.debug(STUDENT_STRING + studentToBeFound + ", is searched"); |
| 127 | + |
| 128 | + student = new Student(student.getStudentId(), "AdamUpdated", 'A'); |
| 129 | + |
| 130 | + mapper.update(student); |
| 131 | + |
| 132 | + LOGGER.debug(STUDENT_STRING + student + ", is updated"); |
| 133 | + LOGGER.debug(STUDENT_STRING + student + ", is going to be deleted"); |
| 134 | + |
| 135 | + mapper.delete(student); |
| 136 | + } |
| 137 | + |
| 138 | + private App() { |
| 139 | + } |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +Program output: |
| 144 | + |
| 145 | +15:05:00.264 [main] DEBUG com.iluwatar.datamapper.App - App.main(), student : Student(studentId=1, name=Adam, grade=A), is inserted |
| 146 | +15:05:00.267 [main] DEBUG com.iluwatar.datamapper.App - App.main(), student : Optional[Student(studentId=1, name=Adam, grade=A)], is searched |
| 147 | +15:05:00.268 [main] DEBUG com.iluwatar.datamapper.App - App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is updated |
| 148 | +15:05:00.268 [main] DEBUG com.iluwatar.datamapper.App - App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is going to be deleted |
| 149 | + |
| 150 | + |
11 | 151 |
|
12 | 152 | This layer consists of one or more mappers (or data access objects) that perform data transfer. The scope of mapper implementations varies.
|
13 | 153 | A generic mapper will handle many different domain entity types, a dedicated mapper will handle one or a few.
|
|
0 commit comments