@@ -7,11 +7,167 @@ permalink: /patterns/unit-of-work/
7
7
categories : Architectural
8
8
tags :
9
9
- Data access
10
+ - Performance
10
11
---
11
12
12
13
## Intent
13
- When a business transaction is completed, all the these updates are sent as one
14
- big unit of work to be persisted in a database in one go so as to minimize database trips.
14
+ When a business transaction is completed, all the the updates are sent as one big unit of work to be persisted
15
+ in one go to minimize database round-trips.
16
+
17
+ ## Explanation
18
+ Real world example
19
+
20
+ > We have a database containing student information. Administrators all over the country are constantly updating this information and it causes high load on the database server. To make the load more manageable we apply to Unit of Work pattern to send many small updates in batches.
21
+
22
+ In plain words
23
+
24
+ > Unit of Work merges many small database updates in single batch to optimize the number of round-trips.
25
+
26
+ [ MartinFowler.com] ( https://martinfowler.com/eaaCatalog/unitOfWork.html ) says
27
+
28
+ > Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
29
+
30
+ ** Programmatic Example**
31
+
32
+ Here's the ` Student ` entity that is being persisted to the database.
33
+
34
+ ``` java
35
+ public class Student {
36
+ private final Integer id;
37
+ private final String name;
38
+ private final String address;
39
+
40
+ public Student (Integer id , String name , String address ) {
41
+ this . id = id;
42
+ this . name = name;
43
+ this . address = address;
44
+ }
45
+
46
+ public String getName () {
47
+ return name;
48
+ }
49
+
50
+ public Integer getId () {
51
+ return id;
52
+ }
53
+
54
+ public String getAddress () {
55
+ return address;
56
+ }
57
+ }
58
+ ```
59
+
60
+ The essence of the implementation is the ` StudentRepository ` implementing the Unit of Work pattern. It maintains a map
61
+ of database operations (` context ` ) that need to be done and when ` commit ` is called it applies them in single batch.
62
+
63
+ ``` java
64
+ public interface IUnitOfWork <T> {
65
+
66
+ String INSERT = " INSERT" ;
67
+ String DELETE = " DELETE" ;
68
+ String MODIFY = " MODIFY" ;
69
+
70
+ void registerNew (T entity );
71
+
72
+ void registerModified (T entity );
73
+
74
+ void registerDeleted (T entity );
75
+
76
+ void commit ();
77
+ }
78
+
79
+ public class StudentRepository implements IUnitOfWork<Student > {
80
+ private static final Logger LOGGER = LoggerFactory . getLogger(StudentRepository . class);
81
+
82
+ private Map<String , List<Student > > context;
83
+ private StudentDatabase studentDatabase;
84
+
85
+ public StudentRepository (Map<String , List<Student > > context , StudentDatabase studentDatabase ) {
86
+ this . context = context;
87
+ this . studentDatabase = studentDatabase;
88
+ }
89
+
90
+ @Override
91
+ public void registerNew (Student student ) {
92
+ LOGGER . info(" Registering {} for insert in context." , student. getName());
93
+ register(student, IUnitOfWork . INSERT );
94
+ }
95
+
96
+ @Override
97
+ public void registerModified (Student student ) {
98
+ LOGGER . info(" Registering {} for modify in context." , student. getName());
99
+ register(student, IUnitOfWork . MODIFY );
100
+
101
+ }
102
+
103
+ @Override
104
+ public void registerDeleted (Student student ) {
105
+ LOGGER . info(" Registering {} for delete in context." , student. getName());
106
+ register(student, IUnitOfWork . DELETE );
107
+ }
108
+
109
+ private void register (Student student , String operation ) {
110
+ var studentsToOperate = context. get(operation);
111
+ if (studentsToOperate == null ) {
112
+ studentsToOperate = new ArrayList<> ();
113
+ }
114
+ studentsToOperate. add(student);
115
+ context. put(operation, studentsToOperate);
116
+ }
117
+
118
+ @Override
119
+ public void commit () {
120
+ if (context == null || context. size() == 0 ) {
121
+ return ;
122
+ }
123
+ LOGGER . info(" Commit started" );
124
+ if (context. containsKey(IUnitOfWork . INSERT )) {
125
+ commitInsert();
126
+ }
127
+
128
+ if (context. containsKey(IUnitOfWork . MODIFY )) {
129
+ commitModify();
130
+ }
131
+ if (context. containsKey(IUnitOfWork . DELETE )) {
132
+ commitDelete();
133
+ }
134
+ LOGGER . info(" Commit finished." );
135
+ }
136
+
137
+ private void commitInsert () {
138
+ var studentsToBeInserted = context. get(IUnitOfWork . INSERT );
139
+ for (var student : studentsToBeInserted) {
140
+ LOGGER . info(" Saving {} to database." , student. getName());
141
+ studentDatabase. insert(student);
142
+ }
143
+ }
144
+
145
+ private void commitModify () {
146
+ var modifiedStudents = context. get(IUnitOfWork . MODIFY );
147
+ for (var student : modifiedStudents) {
148
+ LOGGER . info(" Modifying {} to database." , student. getName());
149
+ studentDatabase. modify(student);
150
+ }
151
+ }
152
+
153
+ private void commitDelete () {
154
+ var deletedStudents = context. get(IUnitOfWork . DELETE );
155
+ for (var student : deletedStudents) {
156
+ LOGGER . info(" Deleting {} to database." , student. getName());
157
+ studentDatabase. delete(student);
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ Finally here's how we use the ` StudentRepository ` and ` commit ` the transaction.
164
+
165
+ ``` java
166
+ studentRepository. registerNew(ram);
167
+ studentRepository. registerModified(shyam);
168
+ studentRepository. registerDeleted(gopi);
169
+ studentRepository. commit();
170
+ ```
15
171
16
172
## Class diagram
17
173
![ alt text] ( etc/unit-of-work.urm.png " unit-of-work ")
@@ -23,6 +179,11 @@ Use the Unit Of Work pattern when
23
179
* To send changes to database as a unit of work which ensures atomicity of the transaction.
24
180
* To reduce number of database calls.
25
181
182
+ ## Tutorials
183
+
184
+ * [ Repository and Unit of Work Pattern] ( https://www.programmingwithwolfgang.com/repository-and-unit-of-work-pattern/ )
185
+ * [ Unit of Work - a Design Pattern] ( https://mono.software/2017/01/13/unit-of-work-a-design-pattern/ )
186
+
26
187
## Credits
27
188
28
189
* [ Design Pattern - Unit Of Work Pattern] ( https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern )
0 commit comments