Implementing Data Isolation with MyBatis Interceptor and Custom Annotations
The article describes how to enforce environment‑based data isolation in a shared database by adding an env column, using a MyBatis interceptor to inject and filter this field at runtime, and employing a custom @InvokeChainSkipEnvRule annotation with AOP to selectively bypass the rule, keeping existing code untouched.
Background
In a multi‑environment deployment (pre‑release, gray, online) a single database is shared. Each table originally lacked an env column, causing data from different environments to mix.
Data Isolation Strategy
All tables were retrofitted with an env field. Historical data were marked with env='all' to keep compatibility. Queries now need to filter by the current environment.
SELECT XXX FROM tableName WHERE env = ${environment} AND ${condition}MyBatis Interceptor Solution
A custom MyBatis interceptor rewrites SQL at runtime: it injects the environment value on INSERT and adds an env IN (${environment},'all') condition on SELECT. This avoids touching DO, Mapper or XML files.
SELECT xxx FROM ${tableName} WHERE env IN (${currentEnv},'all') AND ${otherCondition}The interceptor reads the environment from application.properties and uses JSqlParser to modify the statements.
Custom Annotation & AOP
To make the rule reusable, a custom annotation @InvokeChainSkipEnvRule is defined. Methods annotated with it specify which environments or tables should skip the check.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokeChainSkipEnvRule {
boolean isKip() default true;
String[] skipEnvList() default {};
String[] skipTableList() default {};
}An AOP aspect reads the annotation and stores the rule in a thread‑local context, which the interceptor then consults.
Usage Example
@SneakyThrows
@GetMapping("/importSignedUserData")
@InvokeChainSkipEnvRule(skipEnvList = {"pre"}, skipTableList = {"project"})
public void importSignedUserData(HttpServletRequest request, HttpServletResponse response) {
// business logic
}Refactoring Considerations
Minimize changes to existing code.
Separate business logic from infrastructure concerns.
Prefer a single point of modification (interceptor) for maintainability.
Conclusion
The approach demonstrates how a MyBatis interceptor combined with custom annotations can achieve fine‑grained data isolation and selective sharing across environments while keeping the codebase clean and extensible.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.