-
Notifications
You must be signed in to change notification settings - Fork 35
/
MyBatisDataRepositoryImpl.java
140 lines (117 loc) · 5.36 KB
/
MyBatisDataRepositoryImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package com.clevergang.dbtests.repository.impl.mybatis;
import com.clevergang.dbtests.repository.api.DataRepository;
import com.clevergang.dbtests.repository.api.data.*;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
/**
* Implementation of the DataRepository using MyBatis. One might wonder, why I broke the usual MyBatis usage pattern to directly use @Mapper
* interfaces in the Business Layer and why most of the methods are just delegating to DataRepositoryMapper. I do not see that "usual" pattern
* as a great idea:
* You cannot make any modification to how the SQL is executed, you cannot do any pre or post actions (not even simple logging), etc.
* Therefore, I believe that better design choice is to wrap the @Mapper with custom class (even if it's only Delegator) - on one
* side you loose some of the beauty, on the other side future extensions/modifications are much easier (not to speak about mocking).
* In our case it's necessary anyway because at the end of batch operations (like methods updateDepartments and insertDepartments) we
* expect that the records are already inserted/updated -> you have to call flushStatements() in MyBatis to achieve that.
*
* @author Bretislav Wajtr
*/
@Repository
public class MyBatisDataRepositoryImpl implements DataRepository {
private final DataRepositoryMapper sql;
private final SqlSession batchOperations;
@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
public MyBatisDataRepositoryImpl(DataRepositoryMapper sql, @Qualifier("batch-operations") SqlSession batchOperations) {
this.sql = sql;
this.batchOperations = batchOperations;
}
@Override
public Company findCompany(Integer pid) {
return sql.findCompany(pid);
}
@Override
public Company findCompanyUsingSimpleStaticStatement(Integer pid) {
/*
* !!!!! NOTE THAT you can actually use parameters for SQL with statementType=STATEMENT, but you have to use ${pid} notation
* (notice $ instead of #) in the mapping xml!
*/
return sql.findCompanyStatic(pid);
}
@Override
public void removeProject(Integer pid) {
sql.removeProject(pid);
}
@Override
public Department findDepartment(Integer pid) {
return sql.findDepartment(pid);
}
@Override
public List<Department> findDepartmentsOfCompany(Company company) {
return sql.findDepartmentsOfCompany(company);
}
@Override
public void deleteDepartments(List<Department> departmentsToDelete) {
sql.deleteDepartments(departmentsToDelete);
}
@Override
public void updateDepartments(List<Department> departmentsToUpdate) {
DataRepositoryMapper batchSql = batchOperations.getMapper(DataRepositoryMapper.class);
departmentsToUpdate.forEach(batchSql::updateDepartment);
// we have to flush statements here - the records would be updated only at the end of the transaction otherwise
batchOperations.flushStatements();
}
@Override
public void insertDepartments(List<Department> departmentsToInsert) {
DataRepositoryMapper batchSql = batchOperations.getMapper(DataRepositoryMapper.class);
departmentsToInsert.forEach(batchSql::insertDepartment);
// we have to flush statements here - the records would be inserted only at the end of the transaction otherwise
batchOperations.flushStatements();
}
@Override
public Project findProject(Integer pid) {
return sql.findProject(pid);
}
@Override
public Integer insertProject(Project project) {
sql.insertProject(project);
return project.getPid();
}
@Override
public List<Integer> insertProjects(List<Project> projects) {
DataRepositoryMapper batchSql = batchOperations.getMapper(DataRepositoryMapper.class);
projects.forEach(batchSql::insertProject);
// we have to flush statements here - the records would be inserted only at the end of the transaction otherwise
batchOperations.flushStatements();
// MyBatis can actually return the PIDs from batch operation
return projects.stream().map(Project::getPid).collect(Collectors.toList());
}
@Override
public List<ProjectsWithCostsGreaterThanOutput> getProjectsWithCostsGreaterThan(int totalCostBoundary) {
return sql.getProjectsWithCostsGreaterThan(totalCostBoundary);
}
@Override
public Employee findEmployee(Integer pid) {
return sql.findEmployee(pid);
}
@Override
public List<Employee> employeesWithSalaryGreaterThan(Integer minSalary) {
return sql.employeesWithSalaryGreaterThan(minSalary);
}
@Override
public void updateEmployee(Employee employeeToUpdate) {
sql.updateEmployee(employeeToUpdate);
}
@Override
public RegisterEmployeeOutput callRegisterEmployee(String name, String surname, String email, BigDecimal salary, String departmentName, String companyName) {
return sql.callRegisterEmployee(name, surname, email, salary, departmentName, companyName);
}
@Override
public Integer getProjectsCount() {
return sql.getProjectsCount();
}
}