or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

active-record.mdbootstrap-config.mdcrud-operations.mddatabase-support.mdindex.mdpagination.mdquery-builder.mdrow-operations.mdservice-layer.mdupdate-chain.md

update-chain.mddocs/

0

# UpdateChain Fluent Update API

1

2

Fluent, type-safe update operations with method chaining for readable and maintainable database updates. The UpdateChain provides a modern alternative to traditional update methods, combining field setting, condition building, and execution in a single fluent interface.

3

4

## Capabilities

5

6

### UpdateChain Class

7

8

Fluent update builder that combines field setting capabilities with query condition support. Provides type-safe field updates with lambda expressions and comprehensive condition building.

9

10

```java { .api }

11

/**

12

* Fluent update chain for type-safe field updates and condition building

13

* @param <T> Entity type

14

*/

15

public class UpdateChain<T> extends QueryWrapperAdapter<UpdateChain<T>> implements PropertySetter<UpdateChain<T>> {

16

/**

17

* Create UpdateChain from entity class

18

* Automatically resolves BaseMapper from entity class

19

* @param entityClass entity class type

20

* @return new UpdateChain instance

21

*/

22

public static <T> UpdateChain<T> of(Class<T> entityClass);

23

24

/**

25

* Create UpdateChain from BaseMapper

26

* @param baseMapper mapper instance for the entity

27

* @return new UpdateChain instance

28

*/

29

public static <T> UpdateChain<T> of(BaseMapper<T> baseMapper);

30

31

/**

32

* Create UpdateChain from entity object

33

* Uses object values as update data and resolves mapper automatically

34

* @param entityObject entity instance with update values

35

* @return new UpdateChain instance

36

*/

37

public static <T> UpdateChain<T> of(T entityObject);

38

39

/**

40

* Create UpdateChain from entity object with specific mapper

41

* @param entityObject entity instance with update values

42

* @param baseMapper mapper instance for the entity

43

* @return new UpdateChain instance

44

*/

45

public static <T> UpdateChain<T> of(T entityObject, BaseMapper<T> baseMapper);

46

}

47

```

48

49

### Field Setting Operations

50

51

Set field values for update operations with support for conditional setting and raw SQL expressions.

52

53

```java { .api }

54

// Basic field setting

55

/**

56

* Set field value using property name

57

* @param property field/property name

58

* @param value value to set

59

* @return UpdateChain for method chaining

60

*/

61

public UpdateChain<T> set(String property, Object value);

62

63

/**

64

* Set field value using QueryColumn

65

* @param queryColumn column reference

66

* @param value value to set

67

* @return UpdateChain for method chaining

68

*/

69

public UpdateChain<T> set(QueryColumn queryColumn, Object value);

70

71

/**

72

* Set field value using lambda getter (type-safe)

73

* @param getter lambda expression referencing getter method

74

* @param value value to set

75

* @return UpdateChain for method chaining

76

*/

77

public <L> UpdateChain<T> set(LambdaGetter<L> getter, Object value);

78

79

// Conditional field setting

80

/**

81

* Set field value conditionally using property name

82

* @param property field/property name

83

* @param value value to set

84

* @param isEffective whether to include this set operation

85

* @return UpdateChain for method chaining

86

*/

87

public UpdateChain<T> set(String property, Object value, boolean isEffective);

88

89

/**

90

* Set field value conditionally using QueryColumn

91

* @param queryColumn column reference

92

* @param value value to set

93

* @param isEffective whether to include this set operation

94

* @return UpdateChain for method chaining

95

*/

96

public UpdateChain<T> set(QueryColumn queryColumn, Object value, boolean isEffective);

97

98

/**

99

* Set field value conditionally using lambda getter

100

* @param getter lambda expression referencing getter method

101

* @param value value to set

102

* @param isEffective whether to include this set operation

103

* @return UpdateChain for method chaining

104

*/

105

public <L> UpdateChain<T> set(LambdaGetter<L> getter, Object value, boolean isEffective);

106

107

/**

108

* Set field value with BooleanSupplier condition

109

* @param property field/property name

110

* @param value value to set

111

* @param isEffective supplier providing condition evaluation

112

* @return UpdateChain for method chaining

113

*/

114

public UpdateChain<T> set(String property, Object value, BooleanSupplier isEffective);

115

116

/**

117

* Set field value with Predicate condition

118

* @param property field/property name

119

* @param value value to set

120

* @param isEffective predicate to test the value

121

* @return UpdateChain for method chaining

122

*/

123

public <V> UpdateChain<T> set(String property, V value, Predicate<V> isEffective);

124

```

125

126

### Raw SQL Setting Operations

127

128

Set fields using raw SQL expressions for complex update operations, calculations, and database functions.

129

130

```java { .api }

131

// Raw SQL field setting

132

/**

133

* Set field to raw SQL expression using property name

134

* @param property field/property name

135

* @param value raw SQL expression or database function

136

* @return UpdateChain for method chaining

137

*/

138

public UpdateChain<T> setRaw(String property, Object value);

139

140

/**

141

* Set field to raw SQL expression using QueryColumn

142

* @param queryColumn column reference

143

* @param value raw SQL expression or database function

144

* @return UpdateChain for method chaining

145

*/

146

public UpdateChain<T> setRaw(QueryColumn queryColumn, Object value);

147

148

/**

149

* Set field to raw SQL expression using lambda getter

150

* @param getter lambda expression referencing getter method

151

* @param value raw SQL expression or database function

152

* @return UpdateChain for method chaining

153

*/

154

public <L> UpdateChain<T> setRaw(LambdaGetter<L> getter, Object value);

155

156

// Conditional raw SQL setting

157

/**

158

* Set field to raw SQL expression conditionally using property name

159

* @param property field/property name

160

* @param value raw SQL expression

161

* @param isEffective whether to include this set operation

162

* @return UpdateChain for method chaining

163

*/

164

public UpdateChain<T> setRaw(String property, Object value, boolean isEffective);

165

166

/**

167

* Set field to raw SQL expression conditionally using QueryColumn

168

* @param queryColumn column reference

169

* @param value raw SQL expression

170

* @param isEffective whether to include this set operation

171

* @return UpdateChain for method chaining

172

*/

173

public UpdateChain<T> setRaw(QueryColumn queryColumn, Object value, boolean isEffective);

174

175

/**

176

* Set field to raw SQL expression conditionally using lambda getter

177

* @param getter lambda expression referencing getter method

178

* @param value raw SQL expression

179

* @param isEffective whether to include this set operation

180

* @return UpdateChain for method chaining

181

*/

182

public <L> UpdateChain<T> setRaw(LambdaGetter<L> getter, Object value, boolean isEffective);

183

184

/**

185

* Set field to raw SQL with BooleanSupplier condition

186

* @param property field/property name

187

* @param value raw SQL expression

188

* @param isEffective supplier providing condition evaluation

189

* @return UpdateChain for method chaining

190

*/

191

public UpdateChain<T> setRaw(String property, Object value, BooleanSupplier isEffective);

192

193

/**

194

* Set field to raw SQL with Predicate condition

195

* @param property field/property name

196

* @param value raw SQL expression

197

* @param isEffective predicate to test the value

198

* @return UpdateChain for method chaining

199

*/

200

public <V> UpdateChain<T> setRaw(String property, V value, Predicate<V> isEffective);

201

```

202

203

### Condition Building Operations

204

205

Build WHERE conditions using the same powerful condition system as QueryWrapper with full support for complex logical expressions.

206

207

```java { .api }

208

// WHERE conditions

209

/**

210

* Add WHERE condition using QueryCondition

211

* @param queryCondition condition to add

212

* @return UpdateChain for method chaining

213

*/

214

public UpdateChain<T> where(QueryCondition queryCondition);

215

216

/**

217

* Add WHERE condition using raw SQL

218

* @param sql raw SQL condition

219

* @return UpdateChain for method chaining

220

*/

221

public UpdateChain<T> where(String sql);

222

223

/**

224

* Add WHERE condition using parameterized SQL

225

* @param sql SQL with parameter placeholders

226

* @param params parameter values

227

* @return UpdateChain for method chaining

228

*/

229

public UpdateChain<T> where(String sql, Object... params);

230

231

/**

232

* Add WHERE conditions from Map (key=value)

233

* @param whereConditions map of field names to values

234

* @return UpdateChain for method chaining

235

*/

236

public UpdateChain<T> where(Map<String, Object> whereConditions);

237

238

/**

239

* Add WHERE condition using Consumer for complex logic

240

* @param consumer consumer that configures nested conditions

241

* @return UpdateChain for method chaining

242

*/

243

public UpdateChain<T> where(Consumer<QueryWrapper> consumer);

244

245

// AND conditions

246

/**

247

* Add AND condition using QueryCondition

248

* @param queryCondition condition to add with AND logic

249

* @return UpdateChain for method chaining

250

*/

251

public UpdateChain<T> and(QueryCondition queryCondition);

252

253

/**

254

* Add AND condition using raw SQL

255

* @param sql raw SQL condition

256

* @return UpdateChain for method chaining

257

*/

258

public UpdateChain<T> and(String sql);

259

260

/**

261

* Add AND condition using parameterized SQL

262

* @param sql SQL with parameter placeholders

263

* @param params parameter values

264

* @return UpdateChain for method chaining

265

*/

266

public UpdateChain<T> and(String sql, Object... params);

267

268

/**

269

* Add AND conditions from Map

270

* @param whereConditions map of field names to values

271

* @return UpdateChain for method chaining

272

*/

273

public UpdateChain<T> and(Map<String, Object> whereConditions);

274

275

/**

276

* Add AND condition using Consumer for nested logic

277

* @param consumer consumer that configures nested conditions

278

* @return UpdateChain for method chaining

279

*/

280

public UpdateChain<T> and(Consumer<QueryWrapper> consumer);

281

282

// OR conditions

283

/**

284

* Add OR condition using QueryCondition

285

* @param queryCondition condition to add with OR logic

286

* @return UpdateChain for method chaining

287

*/

288

public UpdateChain<T> or(QueryCondition queryCondition);

289

290

/**

291

* Add OR condition using raw SQL

292

* @param sql raw SQL condition

293

* @return UpdateChain for method chaining

294

*/

295

public UpdateChain<T> or(String sql);

296

297

/**

298

* Add OR condition using parameterized SQL

299

* @param sql SQL with parameter placeholders

300

* @param params parameter values

301

* @return UpdateChain for method chaining

302

*/

303

public UpdateChain<T> or(String sql, Object... params);

304

305

/**

306

* Add OR conditions from Map

307

* @param whereConditions map of field names to values

308

* @return UpdateChain for method chaining

309

*/

310

public UpdateChain<T> or(Map<String, Object> whereConditions);

311

312

/**

313

* Add OR condition using Consumer for nested logic

314

* @param consumer consumer that configures nested conditions

315

* @return UpdateChain for method chaining

316

*/

317

public UpdateChain<T> or(Consumer<QueryWrapper> consumer);

318

```

319

320

### Execution Operations

321

322

Execute the constructed update or delete operations and return results.

323

324

```java { .api }

325

/**

326

* Execute update operation with configured field changes and conditions

327

* @return true if update affected at least one row, false otherwise

328

*/

329

public boolean update();

330

331

/**

332

* Execute delete operation using configured conditions

333

* @return true if delete affected at least one row, false otherwise

334

*/

335

public boolean remove();

336

337

/**

338

* Generate SQL string for debugging and logging purposes

339

* Includes parameter substitution for complete SQL visualization

340

* @return complete SQL string with parameters substituted

341

*/

342

public String toSQL();

343

```

344

345

## Usage Examples

346

347

### Basic Field Updates

348

349

```java

350

// Simple field updates using different approaches

351

UpdateChain.of(User.class)

352

.set("name", "John Doe")

353

.set("email", "john@example.com")

354

.where("id = ?", 1)

355

.update();

356

357

// Type-safe updates with lambda expressions

358

UpdateChain.of(User.class)

359

.set(User::getName, "Jane Smith")

360

.set(User::getEmail, "jane@example.com")

361

.where(USER.ID.eq(1))

362

.update();

363

364

// Using QueryColumn references

365

UpdateChain.of(User.class)

366

.set(USER.NAME, "Bob Wilson")

367

.set(USER.EMAIL, "bob@example.com")

368

.where(USER.ID.eq(1))

369

.update();

370

```

371

372

### Conditional Field Setting

373

374

```java

375

String newEmail = getNewEmail();

376

boolean updateStatus = shouldUpdateStatus();

377

378

UpdateChain.of(User.class)

379

.set("name", "Updated Name")

380

.set("email", newEmail, StringUtil.isNotBlank(newEmail)) // Only set if not blank

381

.set("status", "ACTIVE", updateStatus) // Only set if condition is true

382

.set("lastModified", LocalDateTime.now(), () -> shouldUpdateTimestamp()) // BooleanSupplier

383

.where(USER.ID.eq(userId))

384

.update();

385

386

// Using Predicate for value validation

387

UpdateChain.of(Product.class)

388

.set("price", newPrice, price -> price > 0) // Only set if price is positive

389

.set("category", newCategory, Objects::nonNull) // Only set if not null

390

.where(PRODUCT.ID.eq(productId))

391

.update();

392

```

393

394

### Raw SQL Expressions

395

396

```java

397

// Using database functions and calculations

398

UpdateChain.of(Account.class)

399

.setRaw("balance", "balance + ?", 100.0) // Add to existing balance

400

.setRaw("lastUpdated", "NOW()") // Use database function

401

.setRaw("version", "version + 1") // Increment version

402

.where(ACCOUNT.ID.eq(accountId))

403

.update();

404

405

// Complex calculations

406

UpdateChain.of(Order.class)

407

.setRaw("totalAmount", "quantity * unitPrice * (1 - discount)")

408

.setRaw("tax", "totalAmount * 0.08")

409

.where(ORDER.ID.eq(orderId))

410

.update();

411

412

// Conditional raw SQL

413

boolean applyDiscount = checkDiscountEligibility();

414

UpdateChain.of(Product.class)

415

.set("name", newName)

416

.setRaw("price", "price * 0.9", applyDiscount) // Apply 10% discount conditionally

417

.where(PRODUCT.CATEGORY.eq("ELECTRONICS"))

418

.update();

419

```

420

421

### Complex Conditions

422

423

```java

424

// Multiple AND conditions

425

UpdateChain.of(User.class)

426

.set("status", "INACTIVE")

427

.set("lastLogin", null)

428

.where(USER.LAST_LOGIN.lt(LocalDateTime.now().minusMonths(6)))

429

.and(USER.STATUS.eq("ACTIVE"))

430

.and(USER.EMAIL_VERIFIED.eq(false))

431

.update();

432

433

// OR conditions with nested logic

434

UpdateChain.of(Product.class)

435

.set("onSale", true)

436

.set("salePrice", "price * 0.8")

437

.where(PRODUCT.CATEGORY.eq("CLOTHING"))

438

.or(wrapper -> wrapper

439

.and(PRODUCT.INVENTORY.gt(100))

440

.and(PRODUCT.CREATED_AT.lt(LocalDate.now().minusMonths(3)))

441

)

442

.update();

443

444

// Map-based conditions

445

Map<String, Object> conditions = new HashMap<>();

446

conditions.put("status", "PENDING");

447

conditions.put("priority", "HIGH");

448

449

UpdateChain.of(Task.class)

450

.set("assignee", newAssignee)

451

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

452

.where(conditions)

453

.update();

454

```

455

456

### Batch-Style Updates

457

458

```java

459

// Update multiple fields based on entity state

460

User user = getUserById(userId);

461

UpdateChain.of(User.class)

462

.set(User::getName, user.getName())

463

.set(User::getEmail, user.getEmail())

464

.set(User::getPhone, user.getPhone())

465

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

466

.where(USER.ID.eq(userId))

467

.update();

468

469

// Update with entity object as source

470

User updateData = new User();

471

updateData.setName("Updated Name");

472

updateData.setEmail("updated@example.com");

473

474

UpdateChain.of(updateData) // Use entity as update source

475

.where(USER.ID.eq(userId))

476

.update();

477

```

478

479

### Delete Operations

480

481

```java

482

// Simple delete with conditions

483

UpdateChain.of(User.class)

484

.where(USER.STATUS.eq("DELETED"))

485

.and(USER.LAST_LOGIN.lt(LocalDateTime.now().minusYears(1)))

486

.remove();

487

488

// Conditional delete

489

boolean shouldCleanup = isCleanupScheduled();

490

UpdateChain.of(LogEntry.class)

491

.where(LOG_ENTRY.CREATED_AT.lt(LocalDate.now().minusDays(30)), shouldCleanup)

492

.remove();

493

494

// Delete with complex conditions

495

UpdateChain.of(Session.class)

496

.where(wrapper -> wrapper

497

.and(SESSION.EXPIRED_AT.lt(LocalDateTime.now()))

498

.or(SESSION.LAST_ACTIVITY.lt(LocalDateTime.now().minusHours(24)))

499

)

500

.remove();

501

```

502

503

### SQL Generation and Debugging

504

505

```java

506

// Generate SQL for debugging

507

String sql = UpdateChain.of(User.class)

508

.set("name", "Debug User")

509

.set("status", "ACTIVE")

510

.where(USER.ID.eq(123))

511

.toSQL();

512

513

System.out.println("Generated SQL: " + sql);

514

// Output: UPDATE user SET name = 'Debug User', status = 'ACTIVE' WHERE id = 123

515

516

// Complex update SQL generation

517

String complexSql = UpdateChain.of(Order.class)

518

.setRaw("totalAmount", "quantity * unitPrice")

519

.set("status", "CALCULATED")

520

.where(ORDER.STATUS.eq("PENDING"))

521

.and(ORDER.CREATED_AT.between(startDate, endDate))

522

.toSQL();

523

```

524

525

## Types

526

527

### Supporting Classes and Interfaces

528

529

```java { .api }

530

/**

531

* Interface for setting entity properties with fluent API

532

* @param <R> Return type for method chaining

533

*/

534

public interface PropertySetter<R> {

535

// Field setting methods with various parameter types

536

R set(String property, Object value);

537

R set(QueryColumn property, Object value);

538

<T> R set(LambdaGetter<T> property, Object value);

539

540

// Conditional field setting methods

541

R set(String property, Object value, boolean isEffective);

542

R set(String property, Object value, BooleanSupplier isEffective);

543

<V> R set(String property, V value, Predicate<V> isEffective);

544

545

// Raw SQL field setting methods

546

R setRaw(String property, Object value);

547

R setRaw(QueryColumn property, Object value);

548

<T> R setRaw(LambdaGetter<T> property, Object value);

549

550

// Conditional raw SQL setting methods

551

R setRaw(String property, Object value, boolean isEffective);

552

R setRaw(String property, Object value, BooleanSupplier isEffective);

553

<V> R setRaw(String property, V value, Predicate<V> isEffective);

554

}

555

556

/**

557

* Update wrapper interface for entity modification tracking

558

* @param <T> Entity type

559

*/

560

public interface UpdateWrapper<T> extends PropertySetter<UpdateWrapper<T>>, Serializable {

561

/**

562

* Get map of field modifications

563

* @return map containing field names and their update values

564

*/

565

Map<String, Object> getUpdates();

566

567

/**

568

* Create UpdateWrapper from entity object

569

* @param entity entity instance

570

* @return UpdateWrapper wrapping the entity

571

*/

572

static <T> UpdateWrapper<T> of(T entity);

573

574

/**

575

* Create UpdateWrapper from entity class

576

* @param tClass entity class

577

* @return UpdateWrapper for the entity type

578

*/

579

static <T> UpdateWrapper<T> of(Class<T> tClass);

580

581

/**

582

* Convert back to entity object

583

* @return entity instance with modifications

584

*/

585

T toEntity();

586

}

587

588

/**

589

* Query wrapper adapter providing condition building capabilities

590

* @param <R> Return type for method chaining

591

*/

592

public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends QueryWrapper {

593

// Inherits all condition building methods from QueryWrapper

594

// Returns parameterized type R for proper method chaining

595

}

596

```

597

598

## Integration Patterns

599

600

### With BaseMapper Operations

601

602

UpdateChain integrates seamlessly with existing BaseMapper operations and can be mixed with traditional CRUD methods:

603

604

```java

605

@Service

606

public class UserService {

607

@Autowired

608

private UserMapper userMapper;

609

610

public void updateUserStatus(Long userId, String newStatus) {

611

// Traditional approach

612

User user = userMapper.selectOneById(userId);

613

user.setStatus(newStatus);

614

user.setUpdatedAt(LocalDateTime.now());

615

userMapper.update(user);

616

617

// UpdateChain approach - more readable and explicit

618

UpdateChain.of(User.class)

619

.set(User::getStatus, newStatus)

620

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

621

.where(USER.ID.eq(userId))

622

.update();

623

}

624

625

public void bulkUpdatePrices(String category, BigDecimal multiplier) {

626

// Complex update that would be difficult with entity-based updates

627

UpdateChain.of(Product.class)

628

.setRaw("price", "price * ?", multiplier)

629

.setRaw("updatedAt", "NOW()")

630

.set("modifiedBy", getCurrentUser())

631

.where(PRODUCT.CATEGORY.eq(category))

632

.and(PRODUCT.STATUS.eq("ACTIVE"))

633

.update();

634

}

635

}

636

```

637

638

### Comparison with Traditional Updates

639

640

| Approach | UpdateChain | Traditional Entity Update | BaseMapper updateByQuery |

641

|----------|-------------|-------------------------|-------------------------|

642

| **Readability** | High - fluent, self-documenting | Medium - requires entity manipulation | Low - separate wrapper creation |

643

| **Type Safety** | High - lambda expressions | High - entity properties | Medium - QueryWrapper conditions |

644

| **Flexibility** | High - raw SQL, conditionals | Low - entity constraints | High - full query control |

645

| **Performance** | Optimal - direct SQL | Good - entity mapping | Optimal - direct SQL |

646

| **Maintenance** | Easy - method chaining | Easy - familiar pattern | Complex - wrapper management |

647

648

```java

649

// Traditional entity-based update

650

User user = userMapper.selectOneById(userId);

651

user.setName("New Name");

652

user.setStatus("ACTIVE");

653

userMapper.update(user); // Updates ALL fields

654

655

// UpdateChain - selective field updates

656

UpdateChain.of(User.class)

657

.set("name", "New Name")

658

.set("status", "ACTIVE") // Only updates specified fields

659

.where(USER.ID.eq(userId))

660

.update();

661

662

// Traditional BaseMapper with QueryWrapper

663

QueryWrapper queryWrapper = QueryWrapper.create()

664

.where(USER.ID.eq(userId));

665

User updateEntity = new User();

666

updateEntity.setName("New Name");

667

updateEntity.setStatus("ACTIVE");

668

userMapper.updateByQuery(updateEntity, queryWrapper);

669

670

// UpdateChain - combined in single fluent interface

671

UpdateChain.of(User.class)

672

.set("name", "New Name")

673

.set("status", "ACTIVE")

674

.where(USER.ID.eq(userId))

675

.update();

676

```

677

678

The UpdateChain provides a modern, fluent alternative to traditional update patterns while maintaining full compatibility with existing MyBatis-Flex functionality. It excels at selective field updates, conditional modifications, and complex update scenarios that would be cumbersome with entity-based approaches.