☕ @tusk - TuskLang Active Record ORM in Java

Java Documentation

@tusk - TuskLang Active Record ORM in Java

The @tusk operator provides an elegant Active Record pattern for database operations in Java applications, integrating with Spring Boot's JPA, Hibernate, and enterprise ORM solutions.

Basic Syntax

// TuskLang configuration
User: @tusk{
    table: "users"
    primary_key: "id"
    fillable: ["name", "email", "password"]
    hidden: ["password", "remember_token"]
    timestamps: true
}

user: @User.create({ name: "John Doe" email: "john@example.com" password: @hash_password("secret") })

// Java Spring Boot integration
@Configuration
public class TuskConfig {
    
    @Bean
    public TuskService tuskService(JpaRepositoryFactory factory) {
        return TuskService.builder()
            .repositoryFactory(factory)
            .enableTimestamps(true)
            .enableSoftDeletes(true)
            .build();
    }
}

Model Definition

// Java Tusk model definition
@Entity
@Table(name = "users")
public class User extends TuskModel {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "name", nullable = false)
    private String name;
    
    @Column(name = "email", unique = true, nullable = false)
    private String email;
    
    @Column(name = "password", nullable = false)
    private String password;
    
    @Column(name = "remember_token")
    private String rememberToken;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;
    
    // 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 String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    
    public String getRememberToken() { return rememberToken; }
    public void setRememberToken(String rememberToken) { this.rememberToken = rememberToken; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
    
    public LocalDateTime getUpdatedAt() { return updatedAt; }
    public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
    
    public LocalDateTime getDeletedAt() { return deletedAt; }
    public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
    
    // TuskModel methods
    @Override
    public String getTableName() {
        return "users";
    }
    
    @Override
    public String getPrimaryKey() {
        return "id";
    }
    
    @Override
    public List<String> getFillableFields() {
        return Arrays.asList("name", "email", "password");
    }
    
    @Override
    public List<String> getHiddenFields() {
        return Arrays.asList("password", "remember_token");
    }
    
    @Override
    public boolean hasTimestamps() {
        return true;
    }
    
    @Override
    public boolean hasSoftDeletes() {
        return true;
    }
}
// TuskLang model definition
Product: @tusk{
    table: "products"
    primary_key: "id"
    
    # Mass assignment protection
    fillable: ["name", "description", "price", "category_id"]
    guarded: ["id", "created_at", "updated_at"]
    
    # Hide sensitive fields
    hidden: ["cost", "supplier_id"]
    
    # Automatic timestamps
    timestamps: true  # created_at, updated_at
    
    # Soft deletes
    soft_deletes: true  # deleted_at
    
    # Type casting
    casts: {
        price: "float"
        active: "boolean"
        metadata: "json"
        published_at: "datetime"
    }
    
    # Default values
    defaults: {
        active: true
        price: 0.00
        views: 0
    }
}

CRUD Operations

// Java CRUD operations
@Component
public class UserService {
    
    @Autowired
    private TuskService tuskService;
    
    @Autowired
    private UserRepository userRepository;
    
    // Create
    public User createUser(UserDto userDto) {
        User user = new User();
        user.setName(userDto.getName());
        user.setEmail(userDto.getEmail());
        user.setPassword(hashPassword(userDto.getPassword()));
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        return userRepository.save(user);
    }
    
    public User createUser(Map<String, Object> data) {
        User user = new User();
        
        // Apply fillable fields
        List<String> fillable = user.getFillableFields();
        for (String field : fillable) {
            if (data.containsKey(field)) {
                setFieldValue(user, field, data.get(field));
            }
        }
        
        // Set timestamps
        if (user.hasTimestamps()) {
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
        }
        
        return userRepository.save(user);
    }
    
    // Read
    public User findById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new EntityNotFoundException("User not found with id: " + id));
    }
    
    public User findByIdOrFail(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new EntityNotFoundException("User not found with id: " + id));
    }
    
    public User findByEmail(String email) {
        return userRepository.findByEmail(email)
            .orElse(null);
    }
    
    public User first() {
        return userRepository.findFirstByOrderByIdAsc()
            .orElse(null);
    }
    
    // Update
    public User updateUser(Long id, UserDto userDto) {
        User user = findById(id);
        user.setName(userDto.getName());
        user.setEmail(userDto.getEmail());
        user.setUpdatedAt(LocalDateTime.now());
        
        return userRepository.save(user);
    }
    
    public User updateUser(Long id, Map<String, Object> data) {
        User user = findById(id);
        
        // Apply fillable fields
        List<String> fillable = user.getFillableFields();
        for (String field : fillable) {
            if (data.containsKey(field)) {
                setFieldValue(user, field, data.get(field));
            }
        }
        
        // Update timestamp
        if (user.hasTimestamps()) {
            user.setUpdatedAt(LocalDateTime.now());
        }
        
        return userRepository.save(user);
    }
    
    // Delete
    public void deleteUser(Long id) {
        User user = findById(id);
        
        if (user.hasSoftDeletes()) {
            // Soft delete
            user.setDeletedAt(LocalDateTime.now());
            userRepository.save(user);
        } else {
            // Hard delete
            userRepository.delete(user);
        }
    }
    
    public void forceDeleteUser(Long id) {
        User user = findById(id);
        userRepository.delete(user);
    }
    
    public void restoreUser(Long id) {
        User user = findById(id);
        if (user.hasSoftDeletes() && user.getDeletedAt() != null) {
            user.setDeletedAt(null);
            userRepository.save(user);
        }
    }
    
    private void setFieldValue(User user, String field, Object value) {
        try {
            Field userField = User.class.getDeclaredField(field);
            userField.setAccessible(true);
            userField.set(user, value);
        } catch (Exception e) {
            throw new RuntimeException("Failed to set field: " + field, e);
        }
    }
    
    private String hashPassword(String password) {
        // Implementation for password hashing
        return BCrypt.hashpw(password, BCrypt.gensalt());
    }
}
// TuskLang CRUD operations
crud_operations: {
    # Create
    # Method 1: Using create()
    product: @Product.create({
        name: "Laptop"
        description: "High-performance laptop"
        price: 999.99
        category_id: 5
    })
    
    # Method 2: Using new() and save()
    product: @Product.new()
    product.name: "Tablet"
    product.price: 299.99
    product.save()
    
    # Read
    # Find by primary key
    product: @Product.find(1)
    
    # Find with exception if not found
    product: @Product.findOrFail(1)
    
    # Find by attributes
    user: @User.findBy("email", "john@example.com")
    
    # First record
    first_user: @User.first()
    
    # Update
    # Method 1: Direct update
    product: @Product.find(1)
    product.price: 899.99
    product.save()
    
    # Method 2: Mass update
    @Product.update(1, {
        price: 899.99
        description: "Updated description"
    })
    
    # Delete
    # Soft delete (if enabled)
    product.delete()
    
    # Force delete
    product.forceDelete()
    
    # Restore soft deleted
    product.restore()
}

Querying

// Java querying
@Component
public class UserQueryService {
    
    @Autowired
    private UserRepository userRepository;
    
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    public List<User> getActiveUsers() {
        return userRepository.findByActiveTrue();
    }
    
    public List<User> getUsersByCondition(String field, Object value) {
        return userRepository.findByField(field, value);
    }
    
    public List<User> getUsersByMultipleConditions(Map<String, Object> conditions) {
        return userRepository.findByConditions(conditions);
    }
    
    public List<User> getUsersByOrCondition(String field1, Object value1, String field2, Object value2) {
        return userRepository.findByField1OrField2(field1, value1, field2, value2);
    }
    
    public List<User> getUsersByIds(List<Long> ids) {
        return userRepository.findAllById(ids);
    }
    
    public List<User> getUsersByRange(String field, Object minValue, Object maxValue) {
        return userRepository.findByFieldBetween(field, minValue, maxValue);
    }
    
    public List<User> getUsersByLike(String field, String pattern) {
        return userRepository.findByFieldLike(field, "%" + pattern + "%");
    }
    
    public List<User> getUsersOrdered(String field, String direction) {
        Sort sort = Sort.by(Sort.Direction.fromString(direction), field);
        return userRepository.findAll(sort);
    }
    
    public List<User> getUsersLimited(int limit) {
        PageRequest pageRequest = PageRequest.of(0, limit);
        return userRepository.findAll(pageRequest).getContent();
    }
    
    public Page<User> getUsersPaginated(int page, int size) {
        PageRequest pageRequest = PageRequest.of(page, size);
        return userRepository.findAll(pageRequest);
    }
}
// TuskLang querying
querying: {
    # All records
    products: @Product.all()
    
    # Where conditions
    active_products: @Product.where("active", true).get()
    
    # Multiple conditions
    products: @Product
        .where("price", ">", 100)
        .where("category_id", 5)
        .get()
    
    # Or where
    products: @Product
        .where("category_id", 1)
        .orWhere("category_id", 2)
        .get()
    
    # Where in
    products: @Product.whereIn("id", [1, 2, 3, 4, 5]).get()
    
    # Where between
    products: @Product.whereBetween("price", [100, 500]).get()
    
    # Like queries
    products: @Product.where("name", "like", "%laptop%").get()
    
    # Ordering
    products: @Product.orderBy("price", "desc").get()
    
    # Limiting
    top_products: @Product.orderBy("sales", "desc").limit(10).get()
    
    # Pagination
    page: @request.get.page|1
    products: @Product.paginate(20, @page)
}

Relationships

// Java relationships
@Entity
@Table(name = "users")
public class User extends TuskModel {
    
    // ... existing fields ...
    
    // Has many posts
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Post> posts = new ArrayList<>();
    
    // Has one profile
    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Profile profile;
    
    // Belongs to many roles
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private List<Role> roles = new ArrayList<>();
    
    // Getters and setters for relationships
    public List<Post> getPosts() { return posts; }
    public void setPosts(List<Post> posts) { this.posts = posts; }
    
    public Profile getProfile() { return profile; }
    public void setProfile(Profile profile) { this.profile = profile; }
    
    public List<Role> getRoles() { return roles; }
    public void setRoles(List<Role> roles) { this.roles = roles; }
}

@Entity @Table(name = "posts") public class Post extends TuskModel { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "title") private String title; @Column(name = "content") private String content; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Comment> comments = new ArrayList<>(); @ManyToMany(fetch = FetchType.LAZY) @JoinTable( name = "post_tags", joinColumns = @JoinColumn(name = "post_id"), inverseJoinColumns = @JoinColumn(name = "tag_id") ) private List<Tag> tags = new ArrayList<>(); // Getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public List<Comment> getComments() { return comments; } public void setComments(List<Comment> comments) { this.comments = comments; } public List<Tag> getTags() { return tags; } public void setTags(List<Tag> tags) { this.tags = tags; } }

// TuskLang relationships
relationships: {
    # Define relationships
    User: @tusk{
        table: "users"
        
        # Has many posts
        posts: @hasMany("Post", "user_id")
        
        # Has one profile
        profile: @hasOne("Profile", "user_id")
        
        # Belongs to many roles
        roles: @belongsToMany("Role", "user_roles", "user_id", "role_id")
    }
    
    Post: @tusk{
        table: "posts"
        
        # Belongs to user
        user: @belongsTo("User", "user_id")
        
        # Has many comments
        comments: @hasMany("Comment", "post_id")
        
        # Has many tags through pivot
        tags: @belongsToMany("Tag", "post_tags", "post_id", "tag_id")
    }
    
    # Using relationships
    user: @User.find(1)
    user_posts: user.posts()
    
    # Eager loading
    users: @User.with(["posts", "profile"]).get()
    
    # Lazy eager loading
    user: @User.find(1)
    user.load("posts")
    
    # Query relationships
    users_with_posts: @User.has("posts").get()
    users_with_many_posts: @User.has("posts", ">", 5).get()
}

Scopes

// Java scopes
@Component
public class UserScopeService {
    
    @Autowired
    private UserRepository userRepository;
    
    public List<User> getActiveUsers() {
        return userRepository.findByActiveTrue();
    }
    
    public List<User> getExpensiveUsers(double minPrice) {
        return userRepository.findByTotalSpentGreaterThan(minPrice);
    }
    
    public List<User> getUsersInCategory(Long categoryId) {
        return userRepository.findByCategoryId(categoryId);
    }
    
    public List<User> getActiveExpensiveUsers(double minPrice) {
        return userRepository.findByActiveTrueAndTotalSpentGreaterThan(minPrice);
    }
    
    public List<User> getActiveUsersInCategory(Long categoryId) {
        return userRepository.findByActiveTrueAndCategoryId(categoryId);
    }
    
    public List<User> getUsersByScope(String scope, Object... parameters) {
        switch (scope) {
            case "active":
                return getActiveUsers();
            case "expensive":
                if (parameters.length > 0) {
                    return getExpensiveUsers((Double) parameters[0]);
                }
                return getExpensiveUsers(1000.0);
            case "category":
                if (parameters.length > 0) {
                    return getUsersInCategory((Long) parameters[0]);
                }
                return new ArrayList<>();
            default:
                return new ArrayList<>();
        }
    }
}
// TuskLang scopes
scopes: {
    # Define scopes
    Product: @tusk{
        table: "products"
        
        # Scope methods
        scopes: {
            active: (query) => {
                query.where("active", true)
            }
            
            expensive: (query) => {
                query.where("price", ">", 1000)
            }
            
            inCategory: (query, category_id) => {
                query.where("category_id", @category_id)
            }
        }
    }
    
    # Using scopes
    active_products: @Product.active().get()
    expensive_active: @Product.active().expensive().get()
    category_products: @Product.inCategory(5).active().get()
}

Accessors and Mutators

// Java accessors and mutators
@Entity
@Table(name = "users")
public class User extends TuskModel {
    
    // ... existing fields ...
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    
    @Column(name = "email")
    private String email;
    
    // Accessors (getters)
    public String getFullName() {
        return firstName + " " + lastName;
    }
    
    public String getEmailDomain() {
        if (email != null && email.contains("@")) {
            return email.substring(email.indexOf("@") + 1);
        }
        return null;
    }
    
    public boolean isActive() {
        return getDeletedAt() == null;
    }
    
    public int getAge() {
        if (getDateOfBirth() != null) {
            return Period.between(getDateOfBirth(), LocalDate.now()).getYears();
        }
        return 0;
    }
    
    // Mutators (setters)
    public void setEmail(String email) {
        this.email = email != null ? email.toLowerCase() : null;
    }
    
    public void setPassword(String password) {
        this.password = password != null ? BCrypt.hashpw(password, BCrypt.gensalt()) : null;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName != null ? firstName.trim() : null;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName != null ? lastName.trim() : null;
    }
    
    // Getters and setters for new fields
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    // Additional fields for examples
    @Column(name = "date_of_birth")
    private LocalDate dateOfBirth;
    
    public LocalDate getDateOfBirth() { return dateOfBirth; }
    public void setDateOfBirth(LocalDate dateOfBirth) { this.dateOfBirth = dateOfBirth; }
}
// TuskLang accessors and mutators
accessors_mutators: {
    User: @tusk{
        table: "users"
        
        # Accessors (getters)
        accessors: {
            full_name: (user) => {
                return @user.first_name + " " + @user.last_name
            }
            
            email_domain: (user) => {
                return @user.email.split("@")[1] if @user.email contains "@"
            }
            
            is_active: (user) => {
                return @user.deleted_at == null
            }
            
            age: (user) => {
                return @date.diff(@user.date_of_birth, @date.now(), "years")
            }
        }
        
        # Mutators (setters)
        mutators: {
            email: (user, value) => {
                return @value.lowercase() if @value
            }
            
            password: (user, value) => {
                return @hash_password(@value) if @value
            }
            
            first_name: (user, value) => {
                return @value.trim() if @value
            }
            
            last_name: (user, value) => {
                return @value.trim() if @value
            }
        }
    }
}

Model Events

// Java model events
@Entity
@Table(name = "users")
public class User extends TuskModel {
    
    // ... existing fields ...
    
    @PrePersist
    protected void onCreate() {
        if (hasTimestamps()) {
            setCreatedAt(LocalDateTime.now());
            setUpdatedAt(LocalDateTime.now());
        }
    }
    
    @PreUpdate
    protected void onUpdate() {
        if (hasTimestamps()) {
            setUpdatedAt(LocalDateTime.now());
        }
    }
    
    @PreRemove
    protected void onDelete() {
        // Handle pre-delete logic
        log.info("Deleting user: {}", getId());
    }
    
    @PostLoad
    protected void onLoad() {
        // Handle post-load logic
        log.debug("Loaded user: {}", getId());
    }
    
    @PostPersist
    protected void onPostCreate() {
        // Handle post-create logic
        log.info("Created user: {}", getId());
    }
    
    @PostUpdate
    protected void onPostUpdate() {
        // Handle post-update logic
        log.info("Updated user: {}", getId());
    }
    
    @PostRemove
    protected void onPostDelete() {
        // Handle post-delete logic
        log.info("Deleted user: {}", getId());
    }
}

@Component public class UserEventListener { @EventListener public void handleUserCreated(UserCreatedEvent event) { User user = event.getUser(); // Send welcome email sendWelcomeEmail(user); } @EventListener public void handleUserUpdated(UserUpdatedEvent event) { User user = event.getUser(); // Update search index updateSearchIndex(user); } @EventListener public void handleUserDeleted(UserDeletedEvent event) { User user = event.getUser(); // Clean up related data cleanupUserData(user); } private void sendWelcomeEmail(User user) { // Implementation for sending welcome email } private void updateSearchIndex(User user) { // Implementation for updating search index } private void cleanupUserData(User user) { // Implementation for cleaning up user data } }

// TuskLang model events
model_events: {
    User: @tusk{
        table: "users"
        
        # Model events
        events: {
            # Before events
            before_create: (user) => {
                @user.password = @hash_password(@user.password)
            }
            
            before_update: (user) => {
                @user.updated_at = @date.now()
            }
            
            before_delete: (user) => {
                @log.info("Deleting user: " + @user.id)
            }
            
            # After events
            after_create: (user) => {
                @send_welcome_email(@user)
                @log.info("Created user: " + @user.id)
            }
            
            after_update: (user) => {
                @update_search_index(@user)
                @log.info("Updated user: " + @user.id)
            }
            
            after_delete: (user) => {
                @cleanup_user_data(@user)
                @log.info("Deleted user: " + @user.id)
            }
        }
    }
}

Model Testing

// JUnit test for Tusk models
@SpringBootTest
class UserModelTest {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private TuskService tuskService;
    
    @Test
    void testCreateUser() {
        User user = new User();
        user.setName("John Doe");
        user.setEmail("john@example.com");
        user.setPassword("secret");
        
        User savedUser = userRepository.save(user);
        
        assertThat(savedUser.getId()).isNotNull();
        assertThat(savedUser.getName()).isEqualTo("John Doe");
        assertThat(savedUser.getEmail()).isEqualTo("john@example.com");
        assertThat(savedUser.getCreatedAt()).isNotNull();
        assertThat(savedUser.getUpdatedAt()).isNotNull();
    }
    
    @Test
    void testFindUser() {
        User user = createTestUser();
        User foundUser = userRepository.findById(user.getId()).orElse(null);
        
        assertThat(foundUser).isNotNull();
        assertThat(foundUser.getName()).isEqualTo(user.getName());
    }
    
    @Test
    void testUpdateUser() {
        User user = createTestUser();
        user.setName("Jane Doe");
        
        User updatedUser = userRepository.save(user);
        
        assertThat(updatedUser.getName()).isEqualTo("Jane Doe");
        assertThat(updatedUser.getUpdatedAt()).isAfter(user.getCreatedAt());
    }
    
    @Test
    void testDeleteUser() {
        User user = createTestUser();
        userRepository.delete(user);
        
        User deletedUser = userRepository.findById(user.getId()).orElse(null);
        assertThat(deletedUser).isNull();
    }
    
    @Test
    void testSoftDeleteUser() {
        User user = createTestUser();
        user.setDeletedAt(LocalDateTime.now());
        userRepository.save(user);
        
        User softDeletedUser = userRepository.findById(user.getId()).orElse(null);
        assertThat(softDeletedUser).isNotNull();
        assertThat(softDeletedUser.getDeletedAt()).isNotNull();
    }
    
    @Test
    void testUserRelationships() {
        User user = createTestUser();
        Post post = new Post();
        post.setTitle("Test Post");
        post.setContent("Test Content");
        post.setUser(user);
        
        user.getPosts().add(post);
        userRepository.save(user);
        
        User savedUser = userRepository.findById(user.getId()).orElse(null);
        assertThat(savedUser.getPosts()).hasSize(1);
        assertThat(savedUser.getPosts().get(0).getTitle()).isEqualTo("Test Post");
    }
    
    private User createTestUser() {
        User user = new User();
        user.setName("Test User");
        user.setEmail("test@example.com");
        user.setPassword("secret");
        return userRepository.save(user);
    }
}
// TuskLang model testing
test_tusk_models: {
    # Test user creation
    test_user: @User.create({
        name: "John Doe"
        email: "john@example.com"
        password: "secret"
    })
    assert(@test_user.id != null, "User should have an ID")
    assert(@test_user.name == "John Doe", "User name should match")
    assert(@test_user.created_at != null, "User should have created_at timestamp")
    
    # Test user finding
    found_user: @User.find(@test_user.id)
    assert(@found_user != null, "Should find user by ID")
    assert(@found_user.email == "john@example.com", "User email should match")
    
    # Test user update
    @found_user.name = "Jane Doe"
    @found_user.save()
    updated_user: @User.find(@test_user.id)
    assert(@updated_user.name == "Jane Doe", "User name should be updated")
    
    # Test user deletion
    @updated_user.delete()
    deleted_user: @User.find(@test_user.id)
    assert(@deleted_user == null, "User should be deleted")
    
    # Test relationships
    user_with_posts: @User.with("posts").find(@test_user.id)
    assert(@user_with_posts.posts != null, "User should have posts relationship")
}

Best Practices

1. Model Design

// Design models with proper separation of concerns
@Entity
@Table(name = "users")
public class User extends TuskModel {
    
    // Use proper annotations for validation
    @NotNull
    @Size(min = 2, max = 50)
    @Column(name = "name")
    private String name;
    
    @NotNull
    @Email
    @Column(name = "email", unique = true)
    private String email;
    
    @NotNull
    @Size(min = 8)
    @Column(name = "password")
    private String password;
    
    // Use enums for status fields
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private UserStatus status = UserStatus.ACTIVE;
    
    // Use proper data types
    @Column(name = "date_of_birth")
    private LocalDate dateOfBirth;
    
    @Column(name = "last_login")
    private LocalDateTime lastLogin;
    
    // Use JSON for flexible data
    @Column(name = "metadata", columnDefinition = "json")
    private String metadata;
    
    // Implement proper equals and hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
    
    // Implement toString for debugging
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", status=" + status +
                '}';
    }
}

2. Repository Pattern

// Implement repository pattern for data access
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    Optional<User> findByEmail(String email);
    
    List<User> findByActiveTrue();
    
    List<User> findByStatus(UserStatus status);
    
    List<User> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
    
    @Query("SELECT u FROM User u WHERE u.totalSpent > :amount")
    List<User> findExpensiveUsers(@Param("amount") double amount);
    
    @Query("SELECT COUNT(u) FROM User u WHERE u.status = :status")
    long countByStatus(@Param("status") UserStatus status);
    
    @Query("SELECT u FROM User u JOIN u.posts p WHERE p.createdAt > :date")
    List<User> findUsersWithRecentPosts(@Param("date") LocalDateTime date);
}

@Service public class UserService { @Autowired private UserRepository userRepository; public User createUser(UserDto userDto) { User user = new User(); user.setName(userDto.getName()); user.setEmail(userDto.getEmail()); user.setPassword(hashPassword(userDto.getPassword())); return userRepository.save(user); } public User findByEmail(String email) { return userRepository.findByEmail(email) .orElseThrow(() -> new EntityNotFoundException("User not found")); } public List<User> getActiveUsers() { return userRepository.findByActiveTrue(); } public List<User> getExpensiveUsers(double minAmount) { return userRepository.findExpensiveUsers(minAmount); } }

3. Data Validation

// Implement comprehensive data validation
@Component
public class UserValidationService {
    
    @Autowired
    private UserRepository userRepository;
    
    public ValidationResult validateUser(User user) {
        ValidationResult result = new ValidationResult();
        
        // Validate name
        if (user.getName() == null || user.getName().trim().isEmpty()) {
            result.addError("name", "Name is required");
        } else if (user.getName().length() < 2) {
            result.addError("name", "Name must be at least 2 characters");
        }
        
        // Validate email
        if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            result.addError("email", "Email is required");
        } else if (!isValidEmail(user.getEmail())) {
            result.addError("email", "Invalid email format");
        } else if (isEmailDuplicate(user.getEmail(), user.getId())) {
            result.addError("email", "Email already exists");
        }
        
        // Validate password
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            result.addError("password", "Password is required");
        } else if (user.getPassword().length() < 8) {
            result.addError("password", "Password must be at least 8 characters");
        }
        
        return result;
    }
    
    private boolean isValidEmail(String email) {
        String emailRegex = "^[A-Za-z0-9+_.-]+@(.+)$";
        return email.matches(emailRegex);
    }
    
    private boolean isEmailDuplicate(String email, Long excludeId) {
        Optional<User> existingUser = userRepository.findByEmail(email);
        return existingUser.isPresent() && !existingUser.get().getId().equals(excludeId);
    }
}

public class ValidationResult { private Map<String, List<String>> errors = new HashMap<>(); public void addError(String field, String message) { errors.computeIfAbsent(field, k -> new ArrayList<>()).add(message); } public boolean isValid() { return errors.isEmpty(); } public Map<String, List<String>> getErrors() { return errors; } }

The @tusk operator in Java provides a powerful Active Record pattern that simplifies database operations while maintaining the flexibility and performance of enterprise-grade ORM solutions.