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

query-building.mddocs/

0

# Query Building

1

2

MyBatis-Plus provides flexible query wrapper classes for building complex SQL queries with both string-based and lambda-style condition APIs, supporting all common SQL operations with type safety and fluent interfaces.

3

4

## Capabilities

5

6

### QueryWrapper

7

8

String-based query wrapper for building SQL conditions using column names.

9

10

```java { .api }

11

/**

12

* Query wrapper for building SQL conditions with column names

13

* @param <T> Entity type

14

*/

15

public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>

16

implements Query<QueryWrapper<T>, T, String> {

17

18

// Equality conditions

19

public QueryWrapper<T> eq(String column, Object val);

20

public QueryWrapper<T> ne(String column, Object val);

21

22

// Comparison conditions

23

public QueryWrapper<T> gt(String column, Object val);

24

public QueryWrapper<T> ge(String column, Object val);

25

public QueryWrapper<T> lt(String column, Object val);

26

public QueryWrapper<T> le(String column, Object val);

27

28

// Range conditions

29

public QueryWrapper<T> between(String column, Object val1, Object val2);

30

public QueryWrapper<T> notBetween(String column, Object val1, Object val2);

31

32

// String matching conditions

33

public QueryWrapper<T> like(String column, Object val);

34

public QueryWrapper<T> notLike(String column, Object val);

35

public QueryWrapper<T> likeLeft(String column, Object val);

36

public QueryWrapper<T> likeRight(String column, Object val);

37

38

// Null conditions

39

public QueryWrapper<T> isNull(String column);

40

public QueryWrapper<T> isNotNull(String column);

41

42

// Collection conditions

43

public QueryWrapper<T> in(String column, Collection<?> values);

44

public QueryWrapper<T> notIn(String column, Collection<?> values);

45

public QueryWrapper<T> in(String column, Object... values);

46

public QueryWrapper<T> notIn(String column, Object... values);

47

48

// Subquery conditions

49

public QueryWrapper<T> inSql(String column, String inValue);

50

public QueryWrapper<T> notInSql(String column, String notInValue);

51

52

// Grouping and ordering

53

public QueryWrapper<T> groupBy(String... columns);

54

public QueryWrapper<T> orderByAsc(String... columns);

55

public QueryWrapper<T> orderByDesc(String... columns);

56

public QueryWrapper<T> orderBy(boolean condition, boolean isAsc, String... columns);

57

58

// Having clause

59

public QueryWrapper<T> having(String sqlHaving, Object... params);

60

61

// Logical operators

62

public QueryWrapper<T> or();

63

public QueryWrapper<T> or(boolean condition);

64

public QueryWrapper<T> and(Consumer<QueryWrapper<T>> function);

65

public QueryWrapper<T> or(Consumer<QueryWrapper<T>> function);

66

67

// Nested conditions

68

public QueryWrapper<T> nested(Consumer<QueryWrapper<T>> function);

69

70

// Custom SQL

71

public QueryWrapper<T> apply(String applySql, Object... values);

72

public QueryWrapper<T> last(String lastSql);

73

74

// Existence conditions

75

public QueryWrapper<T> exists(String existsSql);

76

public QueryWrapper<T> notExists(String notExistsSql);

77

78

// Lambda conversion

79

public LambdaQueryWrapper<T> lambda();

80

81

// Column selection

82

public QueryWrapper<T> select(String... sqlSelect);

83

public QueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate);

84

}

85

```

86

87

### LambdaQueryWrapper

88

89

Lambda-style query wrapper providing type-safe property references using method references.

90

91

```java { .api }

92

/**

93

* Lambda query wrapper for type-safe property references

94

* @param <T> Entity type

95

*/

96

public class LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryWrapper<T>>

97

implements Query<LambdaQueryWrapper<T>, T, SFunction<T, ?>> {

98

99

// Equality conditions

100

public LambdaQueryWrapper<T> eq(SFunction<T, ?> fn, Object val);

101

public LambdaQueryWrapper<T> ne(SFunction<T, ?> fn, Object val);

102

103

// Comparison conditions

104

public LambdaQueryWrapper<T> gt(SFunction<T, ?> fn, Object val);

105

public LambdaQueryWrapper<T> ge(SFunction<T, ?> fn, Object val);

106

public LambdaQueryWrapper<T> lt(SFunction<T, ?> fn, Object val);

107

public LambdaQueryWrapper<T> le(SFunction<T, ?> fn, Object val);

108

109

// Range conditions

110

public LambdaQueryWrapper<T> between(SFunction<T, ?> fn, Object val1, Object val2);

111

public LambdaQueryWrapper<T> notBetween(SFunction<T, ?> fn, Object val1, Object val2);

112

113

// String matching conditions

114

public LambdaQueryWrapper<T> like(SFunction<T, ?> fn, Object val);

115

public LambdaQueryWrapper<T> notLike(SFunction<T, ?> fn, Object val);

116

public LambdaQueryWrapper<T> likeLeft(SFunction<T, ?> fn, Object val);

117

public LambdaQueryWrapper<T> likeRight(SFunction<T, ?> fn, Object val);

118

119

// Null conditions

120

public LambdaQueryWrapper<T> isNull(SFunction<T, ?> fn);

121

public LambdaQueryWrapper<T> isNotNull(SFunction<T, ?> fn);

122

123

// Collection conditions

124

public LambdaQueryWrapper<T> in(SFunction<T, ?> fn, Collection<?> values);

125

public LambdaQueryWrapper<T> notIn(SFunction<T, ?> fn, Collection<?> values);

126

public LambdaQueryWrapper<T> in(SFunction<T, ?> fn, Object... values);

127

public LambdaQueryWrapper<T> notIn(SFunction<T, ?> fn, Object... values);

128

129

// Subquery conditions

130

public LambdaQueryWrapper<T> inSql(SFunction<T, ?> fn, String inValue);

131

public LambdaQueryWrapper<T> notInSql(SFunction<T, ?> fn, String notInValue);

132

133

// Grouping and ordering

134

public LambdaQueryWrapper<T> groupBy(SFunction<T, ?>... fns);

135

public LambdaQueryWrapper<T> orderByAsc(SFunction<T, ?>... fns);

136

public LambdaQueryWrapper<T> orderByDesc(SFunction<T, ?>... fns);

137

public LambdaQueryWrapper<T> orderBy(boolean condition, boolean isAsc, SFunction<T, ?>... fns);

138

139

// Having clause

140

public LambdaQueryWrapper<T> having(String sqlHaving, Object... params);

141

142

// Logical operators

143

public LambdaQueryWrapper<T> or();

144

public LambdaQueryWrapper<T> or(boolean condition);

145

public LambdaQueryWrapper<T> and(Consumer<LambdaQueryWrapper<T>> function);

146

public LambdaQueryWrapper<T> or(Consumer<LambdaQueryWrapper<T>> function);

147

148

// Nested conditions

149

public LambdaQueryWrapper<T> nested(Consumer<LambdaQueryWrapper<T>> function);

150

151

// Custom SQL

152

public LambdaQueryWrapper<T> apply(String applySql, Object... values);

153

public LambdaQueryWrapper<T> last(String lastSql);

154

155

// Existence conditions

156

public LambdaQueryWrapper<T> exists(String existsSql);

157

public LambdaQueryWrapper<T> notExists(String notExistsSql);

158

159

// Column selection

160

public LambdaQueryWrapper<T> select(SFunction<T, ?>... fns);

161

public LambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate);

162

}

163

```

164

165

### UpdateWrapper

166

167

String-based update wrapper for building update statements with WHERE conditions.

168

169

```java { .api }

170

/**

171

* Update wrapper for building update statements with column names

172

* @param <T> Entity type

173

*/

174

public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T>>

175

implements Update<UpdateWrapper<T>, String> {

176

177

// Set operations

178

public UpdateWrapper<T> set(String column, Object val);

179

public UpdateWrapper<T> set(boolean condition, String column, Object val);

180

public UpdateWrapper<T> setSql(String setSql);

181

public UpdateWrapper<T> setSql(boolean condition, String setSql);

182

183

// Lambda conversion

184

public LambdaUpdateWrapper<T> lambda();

185

186

// All QueryWrapper methods are also available for WHERE conditions

187

// eq, ne, gt, ge, lt, le, between, like, in, etc.

188

}

189

```

190

191

### LambdaUpdateWrapper

192

193

Lambda-style update wrapper with type-safe property references.

194

195

```java { .api }

196

/**

197

* Lambda update wrapper for type-safe property references

198

* @param <T> Entity type

199

*/

200

public class LambdaUpdateWrapper<T> extends AbstractLambdaWrapper<T, LambdaUpdateWrapper<T>>

201

implements Update<LambdaUpdateWrapper<T>, SFunction<T, ?>> {

202

203

// Set operations

204

public LambdaUpdateWrapper<T> set(SFunction<T, ?> fn, Object val);

205

public LambdaUpdateWrapper<T> set(boolean condition, SFunction<T, ?> fn, Object val);

206

public LambdaUpdateWrapper<T> setSql(String setSql);

207

public LambdaUpdateWrapper<T> setSql(boolean condition, String setSql);

208

209

// All LambdaQueryWrapper methods are also available for WHERE conditions

210

// eq, ne, gt, ge, lt, le, between, like, in, etc.

211

}

212

```

213

214

### Wrappers Utility

215

216

Factory class for creating wrapper instances.

217

218

```java { .api }

219

/**

220

* Utility class for creating wrapper instances

221

*/

222

public final class Wrappers {

223

224

/**

225

* Create an empty QueryWrapper

226

*/

227

public static <T> QueryWrapper<T> query();

228

229

/**

230

* Create a QueryWrapper with entity

231

*/

232

public static <T> QueryWrapper<T> query(T entity);

233

234

/**

235

* Create an empty LambdaQueryWrapper

236

*/

237

public static <T> LambdaQueryWrapper<T> lambdaQuery();

238

239

/**

240

* Create a LambdaQueryWrapper with entity

241

*/

242

public static <T> LambdaQueryWrapper<T> lambdaQuery(T entity);

243

244

/**

245

* Create an empty UpdateWrapper

246

*/

247

public static <T> UpdateWrapper<T> update();

248

249

/**

250

* Create an UpdateWrapper with entity

251

*/

252

public static <T> UpdateWrapper<T> update(T entity);

253

254

/**

255

* Create an empty LambdaUpdateWrapper

256

*/

257

public static <T> LambdaUpdateWrapper<T> lambdaUpdate();

258

259

/**

260

* Create a LambdaUpdateWrapper with entity

261

*/

262

public static <T> LambdaUpdateWrapper<T> lambdaUpdate(T entity);

263

264

/**

265

* Create an empty wrapper (no conditions)

266

*/

267

public static <T> QueryWrapper<T> emptyWrapper();

268

}

269

```

270

271

### ChainWrappers Utility (MyBatis-Plus 3.5.7+)

272

273

Factory class for creating chain wrapper instances, providing fluent chainable query and update operations.

274

275

```java { .api }

276

/**

277

* Utility class for creating chain wrapper instances

278

*/

279

public final class ChainWrappers {

280

281

/**

282

* Create a LambdaQueryChainWrapper for fluent querying

283

* @param mapper BaseMapper instance

284

* @return LambdaQueryChainWrapper instance

285

*/

286

public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(BaseMapper<T> mapper);

287

288

/**

289

* Create a QueryChainWrapper for fluent querying

290

* @param mapper BaseMapper instance

291

* @return QueryChainWrapper instance

292

*/

293

public static <T> QueryChainWrapper<T> queryChain(BaseMapper<T> mapper);

294

295

/**

296

* Create a LambdaUpdateChainWrapper for fluent updating

297

* @param mapper BaseMapper instance

298

* @return LambdaUpdateChainWrapper instance

299

*/

300

public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(BaseMapper<T> mapper);

301

302

/**

303

* Create an UpdateChainWrapper for fluent updating

304

* @param mapper BaseMapper instance

305

* @return UpdateChainWrapper instance

306

*/

307

public static <T> UpdateChainWrapper<T> updateChain(BaseMapper<T> mapper);

308

}

309

```

310

311

## Usage Examples

312

313

**Basic Query Conditions:**

314

315

```java

316

// String-based QueryWrapper

317

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

318

wrapper.eq("name", "John")

319

.gt("age", 18)

320

.like("email", "@gmail.com")

321

.isNotNull("phone");

322

323

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

324

325

// Lambda-based LambdaQueryWrapper (type-safe)

326

LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();

327

lambdaWrapper.eq(User::getName, "John")

328

.gt(User::getAge, 18)

329

.like(User::getEmail, "@gmail.com")

330

.isNotNull(User::getPhone);

331

332

List<User> users = userMapper.selectList(lambdaWrapper);

333

```

334

335

**Complex Logical Conditions:**

336

337

```java

338

// AND and OR combinations

339

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

340

wrapper.eq("status", 1)

341

.and(w -> w.eq("type", "VIP").or().gt("score", 1000))

342

.or(w -> w.eq("level", "ADMIN"));

343

344

// Generates: WHERE status = 1 AND (type = 'VIP' OR score > 1000) OR level = 'ADMIN'

345

346

// Nested conditions

347

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

348

wrapper.eq(User::getStatus, 1)

349

.nested(w -> w.eq(User::getType, "VIP")

350

.or()

351

.gt(User::getScore, 1000));

352

353

// Generates: WHERE status = 1 AND (type = 'VIP' OR score > 1000)

354

```

355

356

**Range and Collection Conditions:**

357

358

```java

359

// Range conditions

360

wrapper.between("age", 18, 65)

361

.notBetween("score", 0, 60);

362

363

// Collection conditions

364

List<String> cities = Arrays.asList("Beijing", "Shanghai", "Guangzhou");

365

wrapper.in("city", cities)

366

.notIn("status", 0, -1);

367

368

// Subquery conditions

369

wrapper.inSql("dept_id", "SELECT id FROM department WHERE name = 'IT'")

370

.notInSql("role_id", "SELECT id FROM role WHERE name = 'GUEST'");

371

```

372

373

**String Matching:**

374

375

```java

376

// Different LIKE patterns

377

wrapper.like("name", "John") // name LIKE '%John%'

378

.likeLeft("email", "gmail.com") // email LIKE '%gmail.com'

379

.likeRight("phone", "138") // phone LIKE '138%'

380

.notLike("address", "temp"); // address NOT LIKE '%temp%'

381

```

382

383

**Ordering and Grouping:**

384

385

```java

386

// Ordering

387

wrapper.orderByAsc("create_time")

388

.orderByDesc("update_time", "id");

389

390

// Dynamic ordering

391

boolean sortByAge = true;

392

wrapper.orderBy(sortByAge, true, "age"); // Conditional ascending sort

393

394

// Grouping with HAVING

395

wrapper.select("dept_id", "COUNT(*) as count")

396

.groupBy("dept_id")

397

.having("COUNT(*) > 5");

398

```

399

400

**Column Selection:**

401

402

```java

403

// Select specific columns

404

wrapper.select("id", "name", "email");

405

406

// Lambda column selection

407

lambdaWrapper.select(User::getId, User::getName, User::getEmail);

408

409

// Conditional column selection

410

wrapper.select(User.class, info -> !info.getColumn().equals("password"));

411

```

412

413

**Update Operations:**

414

415

```java

416

// UpdateWrapper for setting values

417

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

418

updateWrapper.set("status", 1)

419

.set("update_time", LocalDateTime.now())

420

.eq("id", 123);

421

422

userMapper.update(null, updateWrapper);

423

424

// LambdaUpdateWrapper (type-safe)

425

LambdaUpdateWrapper<User> lambdaUpdate = new LambdaUpdateWrapper<>();

426

lambdaUpdate.set(User::getStatus, 1)

427

.set(User::getUpdateTime, LocalDateTime.now())

428

.eq(User::getId, 123);

429

430

userMapper.update(null, lambdaUpdate);

431

432

// Update with entity and conditions

433

User updateUser = new User();

434

updateUser.setStatus(1);

435

436

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

437

wrapper.eq("dept_id", 10).gt("age", 25);

438

439

userMapper.update(updateUser, wrapper);

440

```

441

442

**Using Wrappers Utility:**

443

444

```java

445

// Factory methods for cleaner code

446

import static com.baomidou.mybatisplus.core.conditions.Wrappers.*;

447

448

// Query wrappers

449

List<User> users = userMapper.selectList(

450

query(User.class).eq("status", 1).gt("age", 18)

451

);

452

453

List<User> activeUsers = userMapper.selectList(

454

lambdaQuery(User.class).eq(User::getStatus, 1)

455

.gt(User::getAge, 18)

456

);

457

458

// Update wrappers

459

userMapper.update(null,

460

update(User.class).set("status", 0).eq("id", 123)

461

);

462

463

userMapper.update(null,

464

lambdaUpdate(User.class).set(User::getStatus, 0)

465

.eq(User::getId, 123)

466

);

467

```

468

469

**Custom SQL and Advanced Features:**

470

471

```java

472

// Custom SQL fragments

473

wrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", "2023-11");

474

475

// Raw SQL at the end (use with caution)

476

wrapper.eq("status", 1).last("LIMIT 10");

477

478

// Existence conditions

479

wrapper.exists("SELECT 1 FROM user_role WHERE user_id = user.id AND role_id = 1")

480

.notExists("SELECT 1 FROM user_ban WHERE user_id = user.id");

481

482

// Conditional building

483

String name = getNameParam(); // Could be null

484

Integer minAge = getMinAgeParam(); // Could be null

485

486

wrapper.eq(StringUtils.isNotBlank(name), "name", name)

487

.ge(minAge != null, "age", minAge);

488

```

489

490

**Performance Tips:**

491

492

- Use `LambdaQueryWrapper` for type safety and refactoring support

493

- Prefer method chaining for readability

494

- Use conditional building to avoid null parameter issues

495

- Select only needed columns with `select()` methods

496

- Use `last()` sparingly and never with user input (SQL injection risk)

497

- Consider database indexes for frequently used query conditions