Skip to content
Skillpedia
General coding280k · #89

mybatis-patterns

Helps your agent work with the MyBatis database. Improves query design, transaction usage, and performance.

What it does

This tool helps organize and optimize code that interacts with databases using MyBatis technology. It ensures your queries are safe, efficient, and easy to understand.

When to use it

  • ✓When writing or reviewing how the program accesses data.
  • ✓When deciding between different ways to write database commands.
  • ✓When trying to make the program fetch data faster.

Example of what to ask your AI

“How can I ensure my MyBatis database queries are safe from attacks?”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/affaan-m/ECC/blob/main/pi/core/skills/mybatis-patterns/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/affaan-m/ECC/blob/main/pi/core/skills/mybatis-patterns/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

It works by analyzing your MyBatis code to find common patterns and suggest improvements. This includes checking how data is sent and received, and how transactions are managed.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add affaan-m/ECC --skill mybatis-patterns

Or download just the file:

curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/mybatis-patterns/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

MyBatis Patterns

Use MyBatis when SQL control and explicit mappings matter. Keep SQL readable, make mapper contracts small, and put business transactions in the service layer. Pair this skill with springboot-patterns for application structure, database-migrations for schema changes, postgres-patterns or mysql-patterns for engine-specific SQL, and security-review for untrusted input and access-control concerns.

When to Activate

  • Adding or reviewing MyBatis mapper interfaces or XML files
  • Choosing between XML mappers, annotation mappers, and generated SQL
  • Designing resultMap mappings, joins, nested collections, or projections
  • Reviewing dynamic SQL, parameter binding, pagination, or batch writes
  • Debugging N+1 queries, slow statements, connection use, or transaction bugs
  • Integrating MyBatis-Spring into Spring Boot or an XML-first legacy application

How It Works

Use a thin mapper for persistence operations and keep business rules in a service. A typical flow is:

Controller / batch job -> Service (@Transactional) -> Mapper -> Database
  • Register mappers once, either with @Mapper on each interface or with @MapperScan for a package. Do not mix registration approaches casually.
  • Keep the XML namespace equal to the mapper interface's fully qualified name.
  • Give each statement a stable, descriptive id; treat mapper methods as a persistence API that can be tested independently.
  • Return a domain DTO or projection for read paths instead of exposing a large mutable map when the shape is known.
  • Keep schema changes in migrations. Do not make mapper startup silently create or alter production tables.

Examples

@MapperScan("com.example.user.persistence")
@Configuration
class MyBatisConfig {
}

public interface UserMapper {
  UserSummary findSummaryById(long userId);
}
<mapper namespace="com.example.user.persistence.UserMapper">
  <select id="findSummaryById"
          parameterType="long"
          resultType="com.example.user.persistence.UserSummary">
    SELECT id, display_name AS displayName, status
    FROM users
    WHERE id = #{userId}
  </select>
</mapper>

Parameter Binding and SQL Safety

Use #{...} for values. MyBatis binds it as a prepared-statement parameter. Treat ${...} as raw SQL text: it is only appropriate for a value selected from a closed, application-owned allowlist such as a sort-column map.

private static final Map<String, String> SORT_COLUMNS = createSortColumns();

private static Map<String, String> createSortColumns() {
    Map<String, String> columns = new HashMap<>();
    columns.put("name", "display_name");
    columns.put("created", "created_at");
    return Collections.unmodifiableMap(columns);
}

String sortColumn = SORT_COLUMNS.getOrDefault(request.sort(), "created_at");
String sortDirection = request.descending() ? "DESC" : "ASC";
// The mapper receives only an allowlisted identifier; user input is never
// passed directly to ${sortColumn} or ${sortDirection}.
<select id="findPage" resultType="com.example.user.persistence.UserSummary">
  SELECT id AS id,
         display_name AS displayName,
         status AS status,
         created_at AS createdAt
  FROM users
  WHERE tenant_id = #{tenantId}
  ORDER BY ${sortColumn} ${sortDirection}
  LIMIT #{limit}
</select>

Derive tenantId from the authenticated principal or a server-side tenant context, never from a request field. Authenticate the principal and verify that it is authorized for the tenant before invoking the mapper; keep the tenant_id predicate in SQL as defense in depth.

If possible, avoid ${} entirely by selecting among fixed statements or by using a database-specific query builder. Never interpolate user input into a table name, column name, ORDER BY, WHERE fragment, or SQL expression.

For multiple parameters, use a request object or explicit @Param names:

List<UserSummary> findActive(
    @Param("tenantId") long tenantId,
    @Param("statuses") Set<UserStatus> statuses
);

Do not use the deprecated external parameterMap element. Prefer inline parameter mappings and explicit jdbcType for nullable values when the JDBC driver needs it.

XML, Result Types, and Result Maps

  • Use resultType for a simple one-to-one mapping whose column labels already match the target properties.
  • Use resultMap when aliases, type handlers, nested objects, or collections need explicit mapping.

…

FAQ

What is MyBatis?

MyBatis is a tool that helps Java programs communicate with databases, allowing you to write SQL commands in a more organized way.

What are 'mappers'?

Mappers are like translators between your program's code and SQL commands. They define what data to fetch and how to present it.

Why is query security important?

Insecure queries can allow malicious actors to access or modify your data. This tool helps prevent that.

Details

Original description by the author

MyBatis and MyBatis-Spring patterns for mapper design, XML and annotation SQL, result mapping, dynamic SQL safety, transactions, batching, pagination, and query performance. Use when building or reviewing Java persistence code with MyBatis, Spring Boot, MyBatis-Spring, or MyBatis-based legacy applications.

repo: affaan-m/ECC

Popularity

GitHub stars
280k
Ranking position
#89
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills