or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-system.mdindex.mdmapping-annotations.mdplugin-system.mdsession-management.mdtransaction-management.mdtype-handling.md

mapping-annotations.mddocs/

0

# Mapping Annotations

1

2

Annotation-based SQL mapping system that provides a declarative approach to database operations. These annotations allow you to define SQL statements directly on mapper interface methods, eliminating the need for XML configuration files.

3

4

## Capabilities

5

6

### Core SQL Annotations

7

8

#### @Select

9

10

Defines SQL SELECT statements for data retrieval operations.

11

12

```java { .api }

13

/**

14

* Specifies SQL SELECT statement for retrieving records

15

*/

16

@interface Select {

17

/** SQL SELECT statement(s) */

18

String[] value();

19

}

20

```

21

22

**Usage Examples:**

23

24

```java

25

public interface UserMapper {

26

@Select("SELECT * FROM users WHERE id = #{id}")

27

User findById(@Param("id") Long id);

28

29

@Select("SELECT * FROM users WHERE status = #{status} ORDER BY name")

30

List<User> findByStatus(@Param("status") String status);

31

32

// Multi-statement select

33

@Select({

34

"SELECT u.*, p.name as profile_name",

35

"FROM users u",

36

"LEFT JOIN profiles p ON u.profile_id = p.id",

37

"WHERE u.active = #{active}"

38

})

39

List<UserProfile> findUsersWithProfiles(@Param("active") boolean active);

40

}

41

```

42

43

#### @Insert

44

45

Defines SQL INSERT statements for creating new records.

46

47

```java { .api }

48

/**

49

* Specifies SQL INSERT statement

50

*/

51

@interface Insert {

52

/** SQL INSERT statement(s) */

53

String[] value();

54

}

55

```

56

57

**Usage Examples:**

58

59

```java

60

public interface UserMapper {

61

@Insert("INSERT INTO users (name, email, status) VALUES (#{name}, #{email}, #{status})")

62

int insert(User user);

63

64

// Multi-statement insert

65

@Insert({

66

"INSERT INTO users (name, email, status)",

67

"VALUES (#{name}, #{email}, #{status})"

68

})

69

@Options(useGeneratedKeys = true, keyProperty = "id")

70

int insertWithGeneratedKey(User user);

71

}

72

```

73

74

#### @Update

75

76

Defines SQL UPDATE statements for modifying existing records.

77

78

```java { .api }

79

/**

80

* Specifies SQL UPDATE statement

81

*/

82

@interface Update {

83

/** SQL UPDATE statement(s) */

84

String[] value();

85

}

86

```

87

88

**Usage Examples:**

89

90

```java

91

public interface UserMapper {

92

@Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")

93

int update(User user);

94

95

@Update("UPDATE users SET status = #{status} WHERE id = #{id}")

96

int updateStatus(@Param("id") Long id, @Param("status") String status);

97

}

98

```

99

100

#### @Delete

101

102

Defines SQL DELETE statements for removing records.

103

104

```java { .api }

105

/**

106

* Specifies SQL DELETE statement

107

*/

108

@interface Delete {

109

/** SQL DELETE statement(s) */

110

String[] value();

111

}

112

```

113

114

**Usage Examples:**

115

116

```java

117

public interface UserMapper {

118

@Delete("DELETE FROM users WHERE id = #{id}")

119

int deleteById(@Param("id") Long id);

120

121

@Delete("DELETE FROM users WHERE status = #{status}")

122

int deleteByStatus(@Param("status") String status);

123

}

124

```

125

126

### Dynamic SQL Provider Annotations

127

128

For complex dynamic SQL that can't be expressed in simple annotations, use provider classes.

129

130

#### @SelectProvider

131

132

Uses a provider class method to generate dynamic SELECT statements.

133

134

```java { .api }

135

/**

136

* Specifies provider class/method for dynamic SELECT statements

137

*/

138

@interface SelectProvider {

139

/** Provider class containing the SQL generation method */

140

Class<?> type();

141

142

/** Method name in the provider class */

143

String method();

144

}

145

```

146

147

**Usage Examples:**

148

149

```java

150

public interface UserMapper {

151

@SelectProvider(type = UserSqlProvider.class, method = "findByConditions")

152

List<User> findByConditions(UserSearchCriteria criteria);

153

}

154

155

public class UserSqlProvider {

156

public String findByConditions(UserSearchCriteria criteria) {

157

return new SQL()

158

.SELECT("*")

159

.FROM("users")

160

.WHERE(criteria.getName() != null, "name LIKE #{name}")

161

.WHERE(criteria.getStatus() != null, "status = #{status}")

162

.WHERE(criteria.getMinAge() != null, "age >= #{minAge}")

163

.toString();

164

}

165

}

166

```

167

168

#### @InsertProvider

169

170

Uses a provider class method to generate dynamic INSERT statements.

171

172

```java { .api }

173

/**

174

* Specifies provider class/method for dynamic INSERT statements

175

*/

176

@interface InsertProvider {

177

/** Provider class containing the SQL generation method */

178

Class<?> type();

179

180

/** Method name in the provider class */

181

String method();

182

}

183

```

184

185

#### @UpdateProvider

186

187

Uses a provider class method to generate dynamic UPDATE statements.

188

189

```java { .api }

190

/**

191

* Specifies provider class/method for dynamic UPDATE statements

192

*/

193

@interface UpdateProvider {

194

/** Provider class containing the SQL generation method */

195

Class<?> type();

196

197

/** Method name in the provider class */

198

String method();

199

}

200

```

201

202

#### @DeleteProvider

203

204

Uses a provider class method to generate dynamic DELETE statements.

205

206

```java { .api }

207

/**

208

* Specifies provider class/method for dynamic DELETE statements

209

*/

210

@interface DeleteProvider {

211

/** Provider class containing the SQL generation method */

212

Class<?> type();

213

214

/** Method name in the provider class */

215

String method();

216

}

217

```

218

219

### Result Mapping Annotations

220

221

#### @Results

222

223

Container annotation for defining result mappings between database columns and Java object properties.

224

225

```java { .api }

226

/**

227

* Container for result mappings

228

*/

229

@interface Results {

230

/** Optional result map ID for reuse */

231

String id() default "";

232

233

/** Array of individual result mappings */

234

Result[] value();

235

}

236

```

237

238

#### @Result

239

240

Maps individual database columns to Java object properties.

241

242

```java { .api }

243

/**

244

* Maps column to property with optional type handling

245

*/

246

@interface Result {

247

/** Whether this column represents an ID/primary key */

248

boolean id() default false;

249

250

/** Database column name */

251

String column() default "";

252

253

/** Java property name */

254

String property() default "";

255

256

/** Java type for the property */

257

Class<?> javaType() default void.class;

258

259

/** JDBC type for the column */

260

JdbcType jdbcType() default JdbcType.UNDEFINED;

261

262

/** Custom type handler for conversion */

263

Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

264

265

/** One-to-one association mapping */

266

One one() default @One;

267

268

/** One-to-many association mapping */

269

Many many() default @Many;

270

}

271

```

272

273

**Usage Examples:**

274

275

```java

276

public interface UserMapper {

277

@Select("SELECT id, user_name, email_addr, created_at FROM users WHERE id = #{id}")

278

@Results({

279

@Result(column = "id", property = "id", id = true),

280

@Result(column = "user_name", property = "name"),

281

@Result(column = "email_addr", property = "email"),

282

@Result(column = "created_at", property = "createdAt", javaType = LocalDateTime.class)

283

})

284

User findById(@Param("id") Long id);

285

286

// Reusable result map

287

@Select("SELECT id, user_name, email_addr FROM users")

288

@Results(id = "userResultMap", value = {

289

@Result(column = "id", property = "id", id = true),

290

@Result(column = "user_name", property = "name"),

291

@Result(column = "email_addr", property = "email")

292

})

293

List<User> findAll();

294

295

// Reference existing result map

296

@Select("SELECT id, user_name, email_addr FROM users WHERE status = #{status}")

297

@ResultMap("userResultMap")

298

List<User> findByStatus(@Param("status") String status);

299

}

300

```

301

302

### Association Annotations

303

304

#### @One

305

306

Defines one-to-one associations with nested object loading.

307

308

```java { .api }

309

/**

310

* One-to-one association mapping

311

*/

312

@interface One {

313

/** SELECT statement for loading the associated object */

314

String select() default "";

315

316

/** Fetch type - LAZY or EAGER */

317

FetchType fetchType() default FetchType.DEFAULT;

318

319

/** Result map for the association */

320

String resultMap() default "";

321

}

322

```

323

324

#### @Many

325

326

Defines one-to-many associations with collection loading.

327

328

```java { .api }

329

/**

330

* One-to-many association mapping

331

*/

332

@interface Many {

333

/** SELECT statement for loading the associated collection */

334

String select() default "";

335

336

/** Fetch type - LAZY or EAGER */

337

FetchType fetchType() default FetchType.DEFAULT;

338

339

/** Result map for the association */

340

String resultMap() default "";

341

}

342

```

343

344

**Usage Examples:**

345

346

```java

347

public interface UserMapper {

348

@Select("SELECT * FROM users WHERE id = #{id}")

349

@Results({

350

@Result(column = "id", property = "id", id = true),

351

@Result(column = "name", property = "name"),

352

@Result(column = "profile_id", property = "profile",

353

one = @One(select = "findProfileById", fetchType = FetchType.LAZY)),

354

@Result(column = "id", property = "orders",

355

many = @Many(select = "findOrdersByUserId", fetchType = FetchType.LAZY))

356

})

357

User findUserWithAssociations(@Param("id") Long id);

358

359

@Select("SELECT * FROM profiles WHERE id = #{id}")

360

Profile findProfileById(@Param("id") Long id);

361

362

@Select("SELECT * FROM orders WHERE user_id = #{userId}")

363

List<Order> findOrdersByUserId(@Param("userId") Long userId);

364

}

365

```

366

367

### Configuration Annotations

368

369

#### @Options

370

371

Configures various statement execution options.

372

373

```java { .api }

374

/**

375

* Specifies various statement options

376

*/

377

@interface Options {

378

/** Use cache for this statement */

379

boolean useCache() default true;

380

381

/** Flush cache before executing this statement */

382

boolean flushCache() default false;

383

384

/** Result set type */

385

ResultSetType resultSetType() default ResultSetType.DEFAULT;

386

387

/** Statement type */

388

StatementType statementType() default StatementType.PREPARED;

389

390

/** Fetch size hint for the driver */

391

int fetchSize() default -1;

392

393

/** Query timeout in seconds */

394

int timeout() default -1;

395

396

/** Use generated keys for insert statements */

397

boolean useGeneratedKeys() default false;

398

399

/** Property to store generated key value */

400

String keyProperty() default "";

401

402

/** Column name of the generated key */

403

String keyColumn() default "";

404

405

/** Result set names for procedures with multiple result sets */

406

String resultSets() default "";

407

}

408

```

409

410

**Usage Examples:**

411

412

```java

413

public interface UserMapper {

414

@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")

415

@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")

416

int insert(User user);

417

418

@Select("SELECT * FROM users")

419

@Options(fetchSize = 100, timeout = 30, useCache = false)

420

List<User> findAllWithOptions();

421

422

@Update("UPDATE users SET status = 'INACTIVE'")

423

@Options(flushCache = true)

424

int deactivateAllUsers();

425

}

426

```

427

428

#### @Param

429

430

Specifies parameter names for SQL statements when method parameters don't match placeholders.

431

432

```java { .api }

433

/**

434

* Specifies parameter name for SQL statements

435

*/

436

@interface Param {

437

/** Parameter name to use in SQL */

438

String value();

439

}

440

```

441

442

**Usage Examples:**

443

444

```java

445

public interface UserMapper {

446

@Select("SELECT * FROM users WHERE name = #{userName} AND status = #{userStatus}")

447

List<User> findByNameAndStatus(@Param("userName") String name,

448

@Param("userStatus") String status);

449

450

@Update("UPDATE users SET email = #{newEmail} WHERE id = #{userId}")

451

int updateEmail(@Param("userId") Long id, @Param("newEmail") String email);

452

}

453

```

454

455

#### @SelectKey

456

457

Configures key generation for insert operations.

458

459

```java { .api }

460

/**

461

* Specifies key generation strategy

462

*/

463

@interface SelectKey {

464

/** SQL statement(s) for key generation */

465

String[] statement();

466

467

/** Property to store the generated key */

468

String keyProperty();

469

470

/** Column name of the generated key */

471

String keyColumn() default "";

472

473

/** Execute before the main statement (true) or after (false) */

474

boolean before();

475

476

/** Result type of the key */

477

Class<?> resultType();

478

479

/** Statement type for key generation */

480

StatementType statementType() default StatementType.PREPARED;

481

}

482

```

483

484

**Usage Examples:**

485

486

```java

487

public interface UserMapper {

488

// MySQL auto-increment key

489

@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")

490

@SelectKey(statement = "SELECT LAST_INSERT_ID()",

491

keyProperty = "id",

492

before = false,

493

resultType = Long.class)

494

int insertUser(User user);

495

496

// Oracle sequence key

497

@Insert("INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email})")

498

@SelectKey(statement = "SELECT user_seq.nextval FROM dual",

499

keyProperty = "id",

500

before = true,

501

resultType = Long.class)

502

int insertUserOracle(User user);

503

}

504

```

505

506

### Cache Configuration Annotations

507

508

#### @CacheNamespace

509

510

Configures caching behavior for the entire mapper interface.

511

512

```java { .api }

513

/**

514

* Specifies cache configuration for mapper

515

*/

516

@interface CacheNamespace {

517

/** Cache implementation class */

518

Class<? extends Cache> implementation() default PerpetualCache.class;

519

520

/** Eviction policy classes */

521

Class<? extends Cache> eviction() default LruCache.class;

522

523

/** Flush interval in milliseconds */

524

long flushInterval() default 0;

525

526

/** Maximum cache size */

527

int size() default 1024;

528

529

/** Read/write cache (true) or read-only cache (false) */

530

boolean readWrite() default true;

531

532

/** Use blocking cache to prevent cache stampede */

533

boolean blocking() default false;

534

535

/** Additional cache properties */

536

Property[] properties() default {};

537

}

538

539

@interface Property {

540

String name();

541

String value();

542

}

543

```

544

545

#### @CacheNamespaceRef

546

547

References cache configuration from another mapper.

548

549

```java { .api }

550

/**

551

* References cache configuration from another mapper

552

*/

553

@interface CacheNamespaceRef {

554

/** Referenced mapper class */

555

Class<?> value() default void.class;

556

557

/** Referenced namespace name */

558

String name() default "";

559

}

560

```

561

562

**Usage Examples:**

563

564

```java

565

@CacheNamespace(

566

implementation = PerpetualCache.class,

567

eviction = LruCache.class,

568

flushInterval = 60000,

569

size = 512,

570

readWrite = true,

571

blocking = true

572

)

573

public interface UserMapper {

574

@Select("SELECT * FROM users WHERE id = #{id}")

575

@Options(useCache = true)

576

User findById(@Param("id") Long id);

577

}

578

579

// Reference cache from another mapper

580

@CacheNamespaceRef(UserMapper.class)

581

public interface UserProfileMapper {

582

@Select("SELECT * FROM user_profiles WHERE user_id = #{userId}")

583

UserProfile findByUserId(@Param("userId") Long userId);

584

}

585

```

586

587

### Utility Annotations

588

589

#### @Mapper

590

591

Marks an interface as a MyBatis mapper for component scanning.

592

593

```java { .api }

594

/**

595

* Marks interface as MyBatis mapper

596

*/

597

@interface Mapper {

598

}

599

```

600

601

#### @Flush

602

603

Marks a method to flush batch statements.

604

605

```java { .api }

606

/**

607

* Marks method to flush batch statements

608

*/

609

@interface Flush {

610

}

611

```

612

613

#### @Lang

614

615

Specifies a custom language driver for dynamic SQL processing.

616

617

```java { .api }

618

/**

619

* Specifies language driver for dynamic SQL

620

*/

621

@interface Lang {

622

/** Language driver class */

623

Class<? extends LanguageDriver> value();

624

}

625

```

626

627

**Usage Examples:**

628

629

```java

630

@Mapper

631

public interface UserMapper {

632

@Select("SELECT * FROM users WHERE id = #{id}")

633

User findById(@Param("id") Long id);

634

635

@Flush

636

List<BatchResult> flush();

637

638

@Lang(XMLLanguageDriver.class)

639

@Select("SELECT * FROM users WHERE <if test='name != null'>name = #{name}</if>")

640

List<User> findByCondition(@Param("name") String name);

641

}

642

```

643

644

## Types

645

646

```java { .api }

647

/**

648

* Fetch types for associations

649

*/

650

enum FetchType {

651

/** Use global lazy loading setting */

652

DEFAULT,

653

654

/** Load association eagerly */

655

EAGER,

656

657

/** Load association lazily */

658

LAZY

659

}

660

661

/**

662

* Result set types

663

*/

664

enum ResultSetType {

665

/** Use driver default */

666

DEFAULT,

667

668

/** Forward-only result set */

669

FORWARD_ONLY,

670

671

/** Scroll-insensitive result set */

672

SCROLL_INSENSITIVE,

673

674

/** Scroll-sensitive result set */

675

SCROLL_SENSITIVE

676

}

677

678

/**

679

* Statement types

680

*/

681

enum StatementType {

682

/** Regular statement */

683

STATEMENT,

684

685

/** Prepared statement (default) */

686

PREPARED,

687

688

/** Callable statement for stored procedures */

689

CALLABLE

690

}

691

```