or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

active-record.mdannotations.mdcode-generation.mdcore-crud.mdindex.mdpagination.mdplugins.mdquery-building.mdservice-layer.mdspring-boot.md

active-record.mddocs/

0

# Active Record Pattern

1

2

MyBatis-Plus supports the Active Record pattern, allowing entities to perform database operations directly without requiring separate mapper or service classes, providing a more object-oriented approach to data persistence.

3

4

## Capabilities

5

6

### Model Base Class

7

8

Abstract base class that entities can extend to gain Active Record functionality.

9

10

```java { .api }

11

/**

12

* Active Record pattern base class

13

* @param <T> Entity type extending Model

14

*/

15

public abstract class Model<T extends Model<?>> implements Serializable, Cloneable {

16

17

// ==================== Insert Operations ====================

18

19

/**

20

* Insert current entity

21

* @return true if successful

22

*/

23

public boolean insert();

24

25

/**

26

* Insert or update current entity

27

* @return true if successful

28

*/

29

public boolean insertOrUpdate();

30

31

// ==================== Update Operations ====================

32

33

/**

34

* Update current entity by primary key

35

* @return true if successful

36

*/

37

public boolean updateById();

38

39

/**

40

* Update entities by conditions

41

* @param updateWrapper Update conditions wrapper

42

* @return true if successful

43

*/

44

public boolean update(Wrapper<T> updateWrapper);

45

46

// ==================== Delete Operations ====================

47

48

/**

49

* Delete current entity by primary key

50

* @return true if successful

51

*/

52

public boolean deleteById();

53

54

/**

55

* Delete entities by conditions

56

* @param queryWrapper Query conditions wrapper

57

* @return true if successful

58

*/

59

public boolean delete(Wrapper<T> queryWrapper);

60

61

// ==================== Select Operations ====================

62

63

/**

64

* Select entity by primary key

65

* @return Entity or null

66

*/

67

public T selectById();

68

69

/**

70

* Select entity by primary key with specified ID

71

* @param id Primary key value

72

* @return Entity or null

73

*/

74

public T selectById(Serializable id);

75

76

/**

77

* Select one entity by conditions

78

* @param queryWrapper Query conditions wrapper

79

* @return Entity or null

80

*/

81

public T selectOne(Wrapper<T> queryWrapper);

82

83

/**

84

* Select list of entities by conditions

85

* @param queryWrapper Query conditions wrapper

86

* @return List of entities

87

*/

88

public List<T> selectList(Wrapper<T> queryWrapper);

89

90

/**

91

* Select all entities

92

* @return List of all entities

93

*/

94

public List<T> selectAll();

95

96

/**

97

* Select paginated entities

98

* @param page Pagination parameters

99

* @param queryWrapper Query conditions wrapper

100

* @return Paginated results

101

*/

102

public <E extends IPage<T>> E selectPage(E page, Wrapper<T> queryWrapper);

103

104

/**

105

* Count entities by conditions

106

* @param queryWrapper Query conditions wrapper

107

* @return Count

108

*/

109

public long selectCount(Wrapper<T> queryWrapper);

110

111

/**

112

* Count all entities

113

* @return Total count

114

*/

115

public long selectCount();

116

}

117

```

118

119

## Usage Examples

120

121

**Entity Setup with Active Record:**

122

123

```java

124

@TableName("user")

125

public class User extends Model<User> {

126

@TableId(type = IdType.AUTO)

127

private Long id;

128

129

private String name;

130

private Integer age;

131

private String email;

132

private LocalDateTime createTime;

133

134

// constructors, getters, setters...

135

}

136

```

137

138

**Insert Operations:**

139

140

```java

141

// Create and insert new user

142

User user = new User();

143

user.setName("John Doe");

144

user.setAge(25);

145

user.setEmail("john@example.com");

146

147

boolean success = user.insert();

148

// user.getId() will contain the generated ID

149

150

// Insert or update (upsert)

151

User user = new User();

152

user.setId(1L); // If exists, update; otherwise insert

153

user.setName("Updated Name");

154

user.setAge(26);

155

156

boolean success = user.insertOrUpdate();

157

```

158

159

**Update Operations:**

160

161

```java

162

// Update by primary key

163

User user = new User();

164

user.setId(1L);

165

user.setAge(26); // Only non-null fields are updated

166

167

boolean success = user.updateById();

168

169

// Update with conditions

170

User user = new User();

171

user.setAge(30);

172

173

UpdateWrapper<User> wrapper = new UpdateWrapper<>();

174

wrapper.eq("department", "IT").gt("age", 25);

175

176

boolean success = user.update(wrapper);

177

```

178

179

**Delete Operations:**

180

181

```java

182

// Delete by primary key

183

User user = new User();

184

user.setId(1L);

185

186

boolean success = user.deleteById();

187

188

// Delete with conditions

189

User user = new User();

190

QueryWrapper<User> wrapper = new QueryWrapper<>();

191

wrapper.eq("status", 0).lt("last_login", LocalDateTime.now().minusMonths(6));

192

193

boolean success = user.delete(wrapper);

194

```

195

196

**Select Operations:**

197

198

```java

199

// Select by primary key

200

User user = new User();

201

user.setId(1L);

202

User foundUser = user.selectById(); // Returns loaded user or null

203

204

// Select by specified ID

205

User user = new User();

206

User foundUser = user.selectById(1L);

207

208

// Select one by conditions

209

User user = new User();

210

QueryWrapper<User> wrapper = new QueryWrapper<>();

211

wrapper.eq("email", "john@example.com");

212

User foundUser = user.selectOne(wrapper);

213

214

// Select list by conditions

215

User user = new User();

216

QueryWrapper<User> wrapper = new QueryWrapper<>();

217

wrapper.eq("status", 1).orderByDesc("create_time");

218

List<User> users = user.selectList(wrapper);

219

220

// Select all

221

User user = new User();

222

List<User> allUsers = user.selectAll();

223

224

// Paginated select

225

User user = new User();

226

Page<User> page = new Page<>(1, 10);

227

QueryWrapper<User> wrapper = new QueryWrapper<>();

228

wrapper.eq("status", 1);

229

IPage<User> userPage = user.selectPage(page, wrapper);

230

231

// Count operations

232

User user = new User();

233

QueryWrapper<User> wrapper = new QueryWrapper<>();

234

wrapper.eq("status", 1);

235

long activeUsers = user.selectCount(wrapper);

236

237

long totalUsers = user.selectCount();

238

```

239

240

**Chaining Operations:**

241

242

```java

243

// Method chaining for fluent operations

244

User user = new User()

245

.setName("Alice")

246

.setAge(28)

247

.setEmail("alice@example.com");

248

249

if (user.insert()) {

250

System.out.println("User created with ID: " + user.getId());

251

252

// Update the same instance

253

user.setAge(29);

254

if (user.updateById()) {

255

System.out.println("User updated successfully");

256

}

257

}

258

```

259

260

**Complex Business Logic:**

261

262

```java

263

public class User extends Model<User> {

264

// ... fields and basic methods

265

266

// Custom business methods using Active Record

267

public boolean activate() {

268

this.setStatus(1);

269

this.setActiveTime(LocalDateTime.now());

270

return this.updateById();

271

}

272

273

public boolean deactivate() {

274

this.setStatus(0);

275

this.setInactiveTime(LocalDateTime.now());

276

return this.updateById();

277

}

278

279

public List<User> findSimilarUsers() {

280

QueryWrapper<User> wrapper = new QueryWrapper<>();

281

wrapper.eq("department", this.getDepartment())

282

.eq("role", this.getRole())

283

.ne("id", this.getId());

284

return this.selectList(wrapper);

285

}

286

287

public boolean hasSameEmail() {

288

QueryWrapper<User> wrapper = new QueryWrapper<>();

289

wrapper.eq("email", this.getEmail())

290

.ne("id", this.getId());

291

return this.selectCount(wrapper) > 0;

292

}

293

294

public boolean softDelete() {

295

this.setDeleted(1);

296

this.setDeleteTime(LocalDateTime.now());

297

return this.updateById();

298

}

299

}

300

301

// Usage of custom methods

302

User user = new User().selectById(1L);

303

if (user != null) {

304

if (!user.hasSameEmail()) {

305

user.activate();

306

List<User> similar = user.findSimilarUsers();

307

System.out.println("Found " + similar.size() + " similar users");

308

}

309

}

310

```

311

312

**Error Handling:**

313

314

```java

315

try {

316

User user = new User();

317

user.setName("Test User");

318

user.setEmail("test@example.com");

319

320

if (user.insert()) {

321

System.out.println("User created successfully");

322

} else {

323

System.out.println("Failed to create user");

324

}

325

} catch (Exception e) {

326

System.err.println("Database error: " + e.getMessage());

327

// Handle specific exceptions like duplicate key, constraint violations, etc.

328

}

329

```

330

331

**Performance Considerations:**

332

333

```java

334

// Use batch operations at service layer for multiple records

335

// Active Record is best for single entity operations

336

337

// Good: Single entity operations

338

User user = new User().selectById(id);

339

if (user != null) {

340

user.setLastLogin(LocalDateTime.now());

341

user.updateById();

342

}

343

344

// Better for bulk operations: Use service layer

345

// userService.updateBatchById(users);

346

347

// Use Active Record for business logic methods

348

public class Order extends Model<Order> {

349

public boolean canCancel() {

350

return this.getStatus() == OrderStatus.PENDING

351

&& this.getCreateTime().isAfter(LocalDateTime.now().minusMinutes(30));

352

}

353

354

public boolean cancel() {

355

if (!canCancel()) {

356

return false;

357

}

358

this.setStatus(OrderStatus.CANCELLED);

359

this.setCancelTime(LocalDateTime.now());

360

return this.updateById();

361

}

362

}

363

```

364

365

The Active Record pattern in MyBatis-Plus provides an intuitive, object-oriented approach to database operations while maintaining the full power of the underlying BaseMapper functionality.