0
# Service Layer
1
2
The Service Layer is the core component of MyBatis-Plus Extension, providing a comprehensive abstraction over MyBatis CRUD operations. It consists of the `IService` interface that defines all common database operations and the `ServiceImpl` base class that provides ready-to-use implementations.
3
4
## Core Components
5
6
### IService Interface
7
8
The `IService<T>` interface provides a complete set of CRUD operations for entity management.
9
10
```java { .api }
11
public interface IService<T> {
12
int DEFAULT_BATCH_SIZE = 1000;
13
14
// Save operations
15
boolean save(T entity);
16
boolean saveBatch(Collection<T> entityList);
17
boolean saveBatch(Collection<T> entityList, int batchSize);
18
boolean saveOrUpdate(T entity);
19
boolean saveOrUpdateBatch(Collection<T> entityList);
20
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
21
22
// Remove operations
23
boolean removeById(Serializable id);
24
boolean removeByIds(Collection<? extends Serializable> idList);
25
boolean removeByMap(Map<String, Object> columnMap);
26
boolean remove(Wrapper<T> queryWrapper);
27
boolean removeBatchByIds(Collection<? extends Serializable> idList);
28
29
// Update operations
30
boolean updateById(T entity);
31
boolean update(T entity, Wrapper<T> updateWrapper);
32
boolean updateBatchById(Collection<T> entityList);
33
boolean updateBatchById(Collection<T> entityList, int batchSize);
34
35
// Query operations
36
T getById(Serializable id);
37
Optional<T> getOptById(Serializable id);
38
T getOne(Wrapper<T> queryWrapper);
39
Optional<T> getOneOpt(Wrapper<T> queryWrapper);
40
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
41
Optional<T> getOneOpt(Wrapper<T> queryWrapper, boolean throwEx);
42
Map<String, Object> getMap(Wrapper<T> queryWrapper);
43
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
44
45
// List operations
46
List<T> list();
47
List<T> list(Wrapper<T> queryWrapper);
48
List<T> listByIds(Collection<? extends Serializable> idList);
49
List<T> listByMap(Map<String, Object> columnMap);
50
List<Map<String, Object>> listMaps();
51
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
52
<V> List<V> listObjs();
53
<V> List<V> listObjs(Function<? super Object, V> mapper);
54
<V> List<V> listObjs(Wrapper<T> queryWrapper);
55
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
56
57
// Count operations
58
long count();
59
long count(Wrapper<T> queryWrapper);
60
boolean exists(Wrapper<T> queryWrapper);
61
62
// Pagination operations
63
<E extends IPage<T>> E page(E page);
64
<E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper);
65
<E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper);
66
67
// Chain operations
68
QueryChainWrapper<T> query();
69
LambdaQueryChainWrapper<T> lambdaQuery();
70
KtQueryChainWrapper<T> ktQuery();
71
UpdateChainWrapper<T> update();
72
LambdaUpdateChainWrapper<T> lambdaUpdate();
73
KtUpdateChainWrapper<T> ktUpdate();
74
}
75
```
76
77
### ServiceImpl Base Class
78
79
The `ServiceImpl<M, T>` abstract class provides default implementations for all `IService` methods.
80
81
```java { .api }
82
public abstract class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
83
protected Log log = LogFactory.getLog(getClass());
84
85
@Autowired
86
protected M baseMapper;
87
88
// Access methods
89
public M getBaseMapper();
90
protected Class<T> getEntityClass();
91
protected Class<?> getMapperClass();
92
93
// Batch operations with optimized implementations
94
@Transactional(rollbackFor = Exception.class)
95
public boolean saveBatch(Collection<T> entityList, int batchSize);
96
97
@Transactional(rollbackFor = Exception.class)
98
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
99
100
@Transactional(rollbackFor = Exception.class)
101
public boolean updateBatchById(Collection<T> entityList, int batchSize);
102
103
// Single entity operations
104
public boolean saveOrUpdate(T entity);
105
public T getOne(Wrapper<T> queryWrapper, boolean throwEx);
106
public Optional<T> getOneOpt(Wrapper<T> queryWrapper, boolean throwEx);
107
public Map<String, Object> getMap(Wrapper<T> queryWrapper);
108
public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
109
}
110
```
111
112
## Usage Examples
113
114
### Basic Service Setup
115
116
```java
117
// Define entity
118
@TableName("user")
119
public class User {
120
@TableId
121
private Long id;
122
private String name;
123
private String email;
124
private Boolean active;
125
// getters and setters
126
}
127
128
// Define service interface
129
public interface UserService extends IService<User> {
130
// Add custom methods if needed
131
List<User> findActiveUsers();
132
}
133
134
// Implement service
135
@Service
136
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
137
138
@Override
139
public List<User> findActiveUsers() {
140
return this.list(new QueryWrapper<User>().eq("active", true));
141
}
142
}
143
```
144
145
### Save Operations
146
147
```java
148
@Autowired
149
private UserService userService;
150
151
// Save single entity
152
User user = new User();
153
user.setName("John Doe");
154
user.setEmail("john@example.com");
155
boolean saved = userService.save(user);
156
157
// Save batch
158
List<User> users = Arrays.asList(
159
new User("Alice", "alice@example.com"),
160
new User("Bob", "bob@example.com")
161
);
162
boolean allSaved = userService.saveBatch(users);
163
164
// Save or update (based on primary key presence)
165
User existingUser = userService.getById(1L);
166
existingUser.setEmail("newemail@example.com");
167
boolean updated = userService.saveOrUpdate(existingUser);
168
```
169
170
### Query Operations
171
172
```java
173
// Get by ID
174
User user = userService.getById(1L);
175
Optional<User> optionalUser = userService.getOptById(1L);
176
177
// Get single with conditions
178
User activeUser = userService.getOne(
179
new QueryWrapper<User>()
180
.eq("active", true)
181
.eq("email", "john@example.com")
182
);
183
184
// List operations
185
List<User> allUsers = userService.list();
186
List<User> activeUsers = userService.list(
187
new QueryWrapper<User>().eq("active", true)
188
);
189
190
// Count operations
191
long totalUsers = userService.count();
192
long activeCount = userService.count(
193
new QueryWrapper<User>().eq("active", true)
194
);
195
196
// Check existence
197
boolean hasActiveUsers = userService.exists(
198
new QueryWrapper<User>().eq("active", true)
199
);
200
```
201
202
### Update Operations
203
204
```java
205
// Update by ID
206
User user = userService.getById(1L);
207
user.setEmail("updated@example.com");
208
boolean updated = userService.updateById(user);
209
210
// Update with conditions
211
boolean updated = userService.update(
212
new User().setActive(false),
213
new UpdateWrapper<User>().eq("last_login", null)
214
);
215
216
// Batch update by IDs
217
List<User> users = userService.listByIds(Arrays.asList(1L, 2L, 3L));
218
users.forEach(user -> user.setActive(true));
219
boolean allUpdated = userService.updateBatchById(users);
220
```
221
222
### Remove Operations
223
224
```java
225
// Remove by ID
226
boolean removed = userService.removeById(1L);
227
228
// Remove by IDs
229
boolean allRemoved = userService.removeByIds(Arrays.asList(1L, 2L, 3L));
230
231
// Remove with conditions
232
boolean inactiveRemoved = userService.remove(
233
new QueryWrapper<User>().eq("active", false)
234
);
235
236
// Remove by column map
237
Map<String, Object> conditions = new HashMap<>();
238
conditions.put("active", false);
239
conditions.put("last_login", null);
240
boolean removed = userService.removeByMap(conditions);
241
```
242
243
### Pagination
244
245
```java
246
// Basic pagination
247
Page<User> page = new Page<>(1, 10); // current page 1, size 10
248
Page<User> result = userService.page(page);
249
250
List<User> records = result.getRecords();
251
long total = result.getTotal();
252
long pages = result.getPages();
253
254
// Pagination with conditions
255
Page<User> activePage = userService.page(
256
new Page<>(1, 10),
257
new QueryWrapper<User>().eq("active", true)
258
);
259
260
// Pagination with custom ordering
261
Page<User> orderedPage = new Page<User>(1, 10)
262
.addOrder(OrderItem.desc("created_time"));
263
Page<User> result = userService.page(orderedPage);
264
```
265
266
### Chain Operations
267
268
```java
269
// Query chains
270
List<User> users = userService.query()
271
.eq("active", true)
272
.gt("age", 18)
273
.list();
274
275
User user = userService.lambdaQuery()
276
.eq(User::getActive, true)
277
.eq(User::getEmail, "john@example.com")
278
.one();
279
280
// Update chains
281
boolean updated = userService.update()
282
.set("active", false)
283
.eq("last_login", null)
284
.update();
285
286
boolean updated = userService.lambdaUpdate()
287
.set(User::getActive, false)
288
.isNull(User::getLastLogin)
289
.update();
290
```
291
292
## Advanced Features
293
294
### Custom Batch Size
295
296
```java
297
// Use custom batch size for large datasets
298
List<User> largeUserList = createLargeUserList();
299
boolean saved = userService.saveBatch(largeUserList, 500); // batch size 500
300
```
301
302
### Object Mapping
303
304
```java
305
// Get specific fields as objects
306
List<String> emails = userService.listObjs(
307
new QueryWrapper<User>().select("email").eq("active", true),
308
Object::toString
309
);
310
311
// Get single field value
312
String email = userService.getObj(
313
new QueryWrapper<User>().select("email").eq("id", 1L),
314
Object::toString
315
);
316
```
317
318
### Map Results
319
320
```java
321
// Get results as maps for dynamic field access
322
List<Map<String, Object>> userMaps = userService.listMaps(
323
new QueryWrapper<User>().eq("active", true)
324
);
325
326
Map<String, Object> userMap = userService.getMap(
327
new QueryWrapper<User>().eq("id", 1L)
328
);
329
```
330
331
## Error Handling
332
333
The service layer methods return boolean values for modification operations and null/empty collections for query operations when no results are found. For methods that expect single results, you can use the `throwEx` parameter or Optional variants:
334
335
```java
336
// Will throw exception if multiple results found
337
User user = userService.getOne(wrapper, true);
338
339
// Will return Optional.empty() if no result found
340
Optional<User> optionalUser = userService.getOneOpt(wrapper);
341
342
// Safe approach with Optional
343
Optional<User> user = userService.getOptById(1L);
344
if (user.isPresent()) {
345
// Process user
346
} else {
347
// Handle not found case
348
}
349
```