CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-mybatis-flex--mybatis-flex-core

MyBatis-Flex is an elegant enhancement framework for MyBatis providing type-safe query building, active record patterns, and comprehensive ORM capabilities

Pending
Overview
Eval results
Files

active-record.mddocs/

Active Record Pattern

Entity-centric operations where domain objects handle their own persistence. The Active Record pattern provides a clean, object-oriented approach to database operations by embedding persistence logic directly into entity classes.

Capabilities

Model Base Class

Abstract base class that entities can extend to gain Active Record capabilities. Provides direct persistence methods on entity instances.

/**
 * Abstract base class for Active Record pattern implementation
 * @param <T> Entity type extending Model
 */
public abstract class Model<T extends Model<T>> {
    /**
     * Save current entity (insert or update based on primary key)
     * @return true if operation successful
     */
    public boolean save();
    
    /**
     * Update current entity by primary key
     * @return true if operation successful
     */
    public boolean update();
    
    /**
     * Update current entity ignoring null fields
     * @param ignoreNulls whether to ignore null values
     * @return true if operation successful
     */
    public boolean update(boolean ignoreNulls);
    
    /**
     * Delete current entity by primary key
     * @return true if operation successful
     */
    public boolean remove();
    
    /**
     * Save with Optional return type
     * @return Optional<Boolean> with operation result
     */
    public Optional<Boolean> saveOpt();
    
    /**
     * Update with Optional return type
     * @return Optional<Boolean> with operation result
     */
    public Optional<Boolean> updateOpt();
    
    /**
     * Delete with Optional return type
     * @return Optional<Boolean> with operation result
     */
    public Optional<Boolean> removeOpt();
}

Basic Active Record Usage:

import com.mybatisflex.core.activerecord.Model;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.annotation.Id;

// Entity with Active Record capabilities
@Table("users")
public class User extends Model<User> {
    @Id
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Boolean active;
    
    // Constructors
    public User() {}
    
    public User(String name, Integer age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
        this.active = true;
    }
    
    // Getters and setters...
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public Boolean getActive() { return active; }
    public void setActive(Boolean active) { this.active = active; }
}

// Usage examples
public class UserActiveRecordExample {
    public void demonstrateActiveRecord() {
        // Create and save new user
        User user = new User("Alice", 25, "alice@example.com");
        boolean saved = user.save(); // INSERT operation
        
        // Update existing user
        user.setAge(26);
        user.setEmail("alice.updated@example.com");
        boolean updated = user.update(); // UPDATE operation
        
        // Selective update (ignoring nulls)
        User partialUpdate = new User();
        partialUpdate.setId(user.getId());
        partialUpdate.setAge(27); // Only age will be updated
        partialUpdate.update(true); // ignoreNulls = true
        
        // Delete user
        boolean deleted = user.remove(); // DELETE operation
    }
}

MapperModel Base Class

Enhanced Active Record class that provides direct access to mapper functionality for more advanced operations.

/**
 * Enhanced Active Record with mapper access
 * @param <T> Entity type extending MapperModel
 */
public abstract class MapperModel<T extends MapperModel<T>> extends Model<T> {
    /**
     * Get the mapper instance for this entity type
     * @return BaseMapper instance
     */
    protected BaseMapper<T> getMapper();
    
    /**
     * Perform query operations on this entity type
     * @return QueryWrapper for building queries
     */
    public static QueryWrapper query();
    
    /**
     * Find entity by primary key
     * @param id primary key value
     * @return entity instance or null
     */
    public static <T extends MapperModel<T>> T findById(Serializable id);
    
    /**
     * Find all entities of this type
     * @return list of all entities
     */
    public static <T extends MapperModel<T>> List<T> findAll();
    
    /**
     * Count all entities of this type
     * @return total count
     */
    public static <T extends MapperModel<T>> long count();
}

MapperModel Usage:

@Table("users")
public class User extends MapperModel<User> {
    @Id
    private Long id;
    private String name;
    private Integer age;
    private String email;
    
    // Constructors, getters, setters...
}

// Usage with enhanced capabilities
public class UserMapperModelExample {
    public void demonstrateMapperModel() {
        // Static query methods
        User user = User.findById(1L);
        List<User> allUsers = User.findAll();
        long totalUsers = User.count();
        
        // Custom queries using static method
        List<User> adults = User.query()
            .select()
            .from(User.class)
            .where(USER.AGE.ge(18))
            .list(); // Custom method that executes query
        
        // Direct mapper access for advanced operations
        User user = new User("Bob", 30, "bob@example.com");
        BaseMapper<User> mapper = user.getMapper();
        
        // Use mapper for batch operations
        List<User> users = Arrays.asList(
            new User("Charlie", 28, "charlie@example.com"),
            new User("Diana", 32, "diana@example.com")
        );
        mapper.insertBatch(users);
    }
}

Field Query Operations

Query building focused on specific fields with the Active Record pattern.

/**
 * Field-specific query operations for Active Record
 */
public abstract class Model<T extends Model<T>> {
    /**
     * Create query for specific fields of this entity
     * @param fields field names to query
     * @return FieldsQuery instance
     */
    public FieldsQuery<T> withFields(String... fields);
    
    /**
     * Create query including relationship loading
     * @param relations relationship field names
     * @return RelationsQuery instance
     */
    public RelationsQuery<T> withRelations(String... relations);
}

/**
 * Query builder for field-specific operations
 * @param <T> Entity type
 */
public class FieldsQuery<T> {
    /**
     * Add WHERE conditions
     * @param condition query condition
     * @return FieldsQuery for chaining
     */
    public FieldsQuery<T> where(QueryCondition condition);
    
    /**
     * Execute query and return single result
     * @return single entity or null
     */
    public T one();
    
    /**
     * Execute query and return list of results
     * @return list of entities
     */
    public List<T> list();
    
    /**
     * Execute query with pagination
     * @param page pagination parameters
     * @return page of results
     */
    public Page<T> page(Page<T> page);
}

/**
 * Query builder for relationship loading
 * @param <T> Entity type
 */
public class RelationsQuery<T> {
    /**
     * Add WHERE conditions
     * @param condition query condition
     * @return RelationsQuery for chaining
     */
    public RelationsQuery<T> where(QueryCondition condition);
    
    /**
     * Execute query and return single result with relations
     * @return single entity with loaded relations or null
     */
    public T one();
    
    /**
     * Execute query and return list with relations
     * @return list of entities with loaded relations
     */
    public List<T> list();
}

Field Query Examples:

// Field-specific queries
User user = new User()
    .withFields("name", "email")
    .where(USER.AGE.ge(18))
    .one();

List<User> users = new User()
    .withFields("id", "name", "age")
    .where(USER.ACTIVE.eq(true))
    .list();

// Relationship loading
User userWithOrders = new User()
    .withRelations("orders", "profile")
    .where(USER.ID.eq(1L))
    .one();

List<User> usersWithProfiles = new User()
    .withRelations("profile")
    .where(USER.CITY.eq("New York"))
    .list();

Transaction Support

Active Record operations with transaction management.

/**
 * Transaction support for Active Record operations
 */
public abstract class Model<T extends Model<T>> {
    /**
     * Execute operation within transaction
     * @param operation operation to execute
     * @return operation result
     */
    public static <R> R transaction(Supplier<R> operation);
    
    /**
     * Execute operation within transaction (void return)
     * @param operation operation to execute
     */
    public static void transaction(Runnable operation);
    
    /**
     * Execute operation within transaction with specific isolation level
     * @param isolationLevel transaction isolation level
     * @param operation operation to execute
     * @return operation result
     */
    public static <R> R transaction(TransactionIsolationLevel isolationLevel, Supplier<R> operation);
}

Transaction Examples:

// Simple transaction
boolean result = User.transaction(() -> {
    User user1 = new User("Alice", 25, "alice@example.com");
    User user2 = new User("Bob", 30, "bob@example.com");
    
    return user1.save() && user2.save();
});

// Void transaction
User.transaction(() -> {
    User user = User.findById(1L);
    user.setAge(user.getAge() + 1);
    user.update();
    
    // Create audit log
    AuditLog log = new AuditLog("User age updated", user.getId());
    log.save();
});

// Transaction with isolation level
User result = User.transaction(TransactionIsolationLevel.READ_COMMITTED, () -> {
    User user = User.findById(1L);
    user.setLastLoginTime(new Date());
    user.update();
    return user;
});

Types

// Active Record base types
public interface Serializable {
    // Marker interface for primary key types
}

// Query result types
public class FieldsQuery<T> {
    public FieldsQuery<T> where(QueryCondition condition);
    public T one();
    public List<T> list();
    public Page<T> page(Page<T> page);
}

public class RelationsQuery<T> {
    public RelationsQuery<T> where(QueryCondition condition);
    public T one();
    public List<T> list();
}

// Transaction types
public enum TransactionIsolationLevel {
    READ_UNCOMMITTED,
    READ_COMMITTED,
    REPEATABLE_READ,
    SERIALIZABLE
}

// Functional interfaces for transactions
@FunctionalInterface
public interface Supplier<T> {
    T get();
}

@FunctionalInterface
public interface Runnable {
    void run();
}

Install with Tessl CLI

npx tessl i tessl/maven-com-mybatis-flex--mybatis-flex-core

docs

active-record.md

bootstrap-config.md

crud-operations.md

database-support.md

index.md

pagination.md

query-builder.md

row-operations.md

service-layer.md

update-chain.md

tile.json