CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-baomidou--mybatis-plus

MyBatis-Plus is an enhanced toolkit for MyBatis providing CRUD operations, query wrappers, pagination, code generation, and Spring Boot integration.

Pending
Overview
Eval results
Files

active-record.mddocs/

Active Record Pattern

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.

Capabilities

Model Base Class

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

/**
 * Active Record pattern base class
 * @param <T> Entity type extending Model
 */
public abstract class Model<T extends Model<?>> implements Serializable, Cloneable {
    
    // ==================== Insert Operations ====================
    
    /**
     * Insert current entity
     * @return true if successful
     */
    public boolean insert();
    
    /**
     * Insert or update current entity
     * @return true if successful
     */
    public boolean insertOrUpdate();
    
    // ==================== Update Operations ====================
    
    /**
     * Update current entity by primary key
     * @return true if successful
     */
    public boolean updateById();
    
    /**
     * Update entities by conditions
     * @param updateWrapper Update conditions wrapper
     * @return true if successful
     */
    public boolean update(Wrapper<T> updateWrapper);
    
    // ==================== Delete Operations ====================
    
    /**
     * Delete current entity by primary key
     * @return true if successful
     */
    public boolean deleteById();
    
    /**
     * Delete entities by conditions
     * @param queryWrapper Query conditions wrapper
     * @return true if successful
     */
    public boolean delete(Wrapper<T> queryWrapper);
    
    // ==================== Select Operations ====================
    
    /**
     * Select entity by primary key
     * @return Entity or null
     */
    public T selectById();
    
    /**
     * Select entity by primary key with specified ID
     * @param id Primary key value
     * @return Entity or null
     */
    public T selectById(Serializable id);
    
    /**
     * Select one entity by conditions
     * @param queryWrapper Query conditions wrapper
     * @return Entity or null
     */
    public T selectOne(Wrapper<T> queryWrapper);
    
    /**
     * Select list of entities by conditions
     * @param queryWrapper Query conditions wrapper
     * @return List of entities
     */
    public List<T> selectList(Wrapper<T> queryWrapper);
    
    /**
     * Select all entities
     * @return List of all entities
     */
    public List<T> selectAll();
    
    /**
     * Select paginated entities
     * @param page Pagination parameters
     * @param queryWrapper Query conditions wrapper
     * @return Paginated results
     */
    public <E extends IPage<T>> E selectPage(E page, Wrapper<T> queryWrapper);
    
    /**
     * Count entities by conditions
     * @param queryWrapper Query conditions wrapper
     * @return Count
     */
    public long selectCount(Wrapper<T> queryWrapper);
    
    /**
     * Count all entities
     * @return Total count
     */
    public long selectCount();
}

Usage Examples

Entity Setup with Active Record:

@TableName("user")
public class User extends Model<User> {
    @TableId(type = IdType.AUTO)
    private Long id;
    
    private String name;
    private Integer age;
    private String email;
    private LocalDateTime createTime;
    
    // constructors, getters, setters...
}

Insert Operations:

// Create and insert new user
User user = new User();
user.setName("John Doe");
user.setAge(25);
user.setEmail("john@example.com");

boolean success = user.insert();
// user.getId() will contain the generated ID

// Insert or update (upsert)
User user = new User();
user.setId(1L); // If exists, update; otherwise insert
user.setName("Updated Name");
user.setAge(26);

boolean success = user.insertOrUpdate();

Update Operations:

// Update by primary key
User user = new User();
user.setId(1L);
user.setAge(26); // Only non-null fields are updated

boolean success = user.updateById();

// Update with conditions
User user = new User();
user.setAge(30);

UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("department", "IT").gt("age", 25);

boolean success = user.update(wrapper);

Delete Operations:

// Delete by primary key
User user = new User();
user.setId(1L);

boolean success = user.deleteById();

// Delete with conditions
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 0).lt("last_login", LocalDateTime.now().minusMonths(6));

boolean success = user.delete(wrapper);

Select Operations:

// Select by primary key
User user = new User();
user.setId(1L);
User foundUser = user.selectById(); // Returns loaded user or null

// Select by specified ID
User user = new User();
User foundUser = user.selectById(1L);

// Select one by conditions
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("email", "john@example.com");
User foundUser = user.selectOne(wrapper);

// Select list by conditions
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1).orderByDesc("create_time");
List<User> users = user.selectList(wrapper);

// Select all
User user = new User();
List<User> allUsers = user.selectAll();

// Paginated select
User user = new User();
Page<User> page = new Page<>(1, 10);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1);
IPage<User> userPage = user.selectPage(page, wrapper);

// Count operations
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1);
long activeUsers = user.selectCount(wrapper);

long totalUsers = user.selectCount();

Chaining Operations:

// Method chaining for fluent operations
User user = new User()
    .setName("Alice")
    .setAge(28)
    .setEmail("alice@example.com");

if (user.insert()) {
    System.out.println("User created with ID: " + user.getId());
    
    // Update the same instance
    user.setAge(29);
    if (user.updateById()) {
        System.out.println("User updated successfully");
    }
}

Complex Business Logic:

public class User extends Model<User> {
    // ... fields and basic methods
    
    // Custom business methods using Active Record
    public boolean activate() {
        this.setStatus(1);
        this.setActiveTime(LocalDateTime.now());
        return this.updateById();
    }
    
    public boolean deactivate() {
        this.setStatus(0);
        this.setInactiveTime(LocalDateTime.now());
        return this.updateById();
    }
    
    public List<User> findSimilarUsers() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("department", this.getDepartment())
               .eq("role", this.getRole())
               .ne("id", this.getId());
        return this.selectList(wrapper);
    }
    
    public boolean hasSameEmail() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("email", this.getEmail())
               .ne("id", this.getId());
        return this.selectCount(wrapper) > 0;
    }
    
    public boolean softDelete() {
        this.setDeleted(1);
        this.setDeleteTime(LocalDateTime.now());
        return this.updateById();
    }
}

// Usage of custom methods
User user = new User().selectById(1L);
if (user != null) {
    if (!user.hasSameEmail()) {
        user.activate();
        List<User> similar = user.findSimilarUsers();
        System.out.println("Found " + similar.size() + " similar users");
    }
}

Error Handling:

try {
    User user = new User();
    user.setName("Test User");
    user.setEmail("test@example.com");
    
    if (user.insert()) {
        System.out.println("User created successfully");
    } else {
        System.out.println("Failed to create user");
    }
} catch (Exception e) {
    System.err.println("Database error: " + e.getMessage());
    // Handle specific exceptions like duplicate key, constraint violations, etc.
}

Performance Considerations:

// Use batch operations at service layer for multiple records
// Active Record is best for single entity operations

// Good: Single entity operations
User user = new User().selectById(id);
if (user != null) {
    user.setLastLogin(LocalDateTime.now());
    user.updateById();
}

// Better for bulk operations: Use service layer
// userService.updateBatchById(users);

// Use Active Record for business logic methods
public class Order extends Model<Order> {
    public boolean canCancel() {
        return this.getStatus() == OrderStatus.PENDING 
            && this.getCreateTime().isAfter(LocalDateTime.now().minusMinutes(30));
    }
    
    public boolean cancel() {
        if (!canCancel()) {
            return false;
        }
        this.setStatus(OrderStatus.CANCELLED);
        this.setCancelTime(LocalDateTime.now());
        return this.updateById();
    }
}

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.

Install with Tessl CLI

npx tessl i tessl/maven-com-baomidou--mybatis-plus

docs

active-record.md

annotations.md

code-generation.md

core-crud.md

index.md

pagination.md

plugins.md

query-building.md

service-layer.md

spring-boot.md

tile.json