Backend Development 11 min read

Implementing Data Permission Interceptor in MyBatis-Plus with Custom Annotations

This tutorial explains how to globally enforce data‑permission filtering in MyBatis‑Plus by creating a custom @UserDataPermission annotation, implementing an InnerInterceptor that modifies SQL WHERE clauses based on user roles, and configuring the interceptor within the MyBatis‑Plus plugin system.

Architecture Digest
Architecture Digest
Architecture Digest
Implementing Data Permission Interceptor in MyBatis-Plus with Custom Annotations

In many backend projects, data access must be restricted based on the current user's role, and adding checks to every mapper method can be cumbersome.

This article shows how to use MyBatis‑Plus's InnerInterceptor to inject a data‑permission filter globally, while limiting its effect to methods annotated with a custom @UserDataPermission annotation.

First, define the annotation:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserDataPermission {}

Then implement an interceptor that extends JsqlParserSupport and implements InnerInterceptor . In beforeQuery it parses the original SQL, and in processSelect it adds a WHERE clause based on the annotation.

public class MyDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
    private MyDataPermissionHandler dataPermissionHandler;
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter,
                            RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) return;
        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        mpBs.sql(this.parserSingle(mpBs.sql(), ms.getId()));
    }
    @Override
    protected void processSelect(Select select, int index, String sql, Object obj) {
        // add where condition
    }
}

The handler builds the actual SQL fragment. It retrieves the current user, determines the data scope (ALL, DEPT, MYSELF) from role enums, and returns an AndExpression that combines the original WHERE with the permission condition.

public class MyDataPermissionHandler {
    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        // obtain user and role, build expression
    }
}

Register the interceptor in a MybatisPlusInterceptor bean, optionally chaining it with the pagination interceptor.

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor();
    dataPermissionInterceptor.setDataPermissionHandler(new MyDataPermissionHandler());
    interceptor.addInnerInterceptor(dataPermissionInterceptor);
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}

For projects that already configure a MybatisPlusInterceptor , the data‑permission interceptor can be inserted into the existing interceptor list to avoid breaking existing settings.

Advanced version adds role‑based scope handling. Define DataScope and DataPermission enums, then modify the handler to generate IN expressions for department‑level access or equality for self‑access.

public enum DataScope { ALL, DEPT, MYSELF }

public enum DataPermission {
    DATA_MANAGER("Data Manager", "DATA_MANAGER", DataScope.ALL),
    DATA_AUDITOR("Data Auditor", "DATA_AUDITOR", DataScope.DEPT),
    DATA_OPERATOR("Data Operator", "DATA_OPERATOR", DataScope.MYSELF);
    // getters and utility methods
}

Finally, annotate mapper methods (or the whole mapper interface) with @UserDataPermission so that the interceptor applies only to those queries.

@UserDataPermission
List
selectAllCustomerPage(IPage
page,
    @Param("customerName") String customerName);

Remember to add the interceptor to MyBatis‑Plus, ensure a business‑filter field such as creator_code exists, and adjust the field name if needed.

Javabackend developmentCustom AnnotationInterceptorMyBatis-PlusData Permission
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.