principle
Use an interceptor before executing sql in mybatis,
Add the specified query conditions after SQL
For example, your table uses user_id as the distinction
Then you need to add the logic of user_id = #{userId} to the sql interceptor
accomplish
The relevant knowledge of mybatis interceptor will not be described in detail. You can intercept in the four stages of mybatis
Execute , MappedStatment , ParamHanlder , and ResultHandler
You can do something in detail at each stage by Baidu.
@AuthFilter(userFiled = "user_id" , ignoreOrgFiled = true) Page getUserMsgPage(@Param("page")Page page , @Param("param") MsgUserRefDto param , @Param("loginId") String loginId , @Param("orderBy")String orderBy);
The specific effect is that we hope that the above sql will be automatically spliced with and user_id = 1 when executing to filter the data of the specified user.
Configuration File
@Configuration @AutoConfigureAfter() public class MybatisConfig { @Autowired private List<SqlSessionFactory> sqlSessionFactoryList; @PostConstruct void mybatisConfigurationCustomizer() { AuthInterceptor authInterceptor = new AuthInterceptor(); (o->{ ().addInterceptor(authInterceptor); }); } }
Custom annotations
@Retention() @Target({ , }) @Documented public @interface AuthFilter { String userFiled() default "userId"; String orgFiled() default "orgId"; boolean ignoreUserFiled() default false; boolean ignoreOrgFiled() default false; }
Specific interceptor logic
Among them, GlobalHolder is the container in each system that stores user login information.
@Slf4j @Component @Intercepts({@Signature( type = , method = "query", args = {, , , } ), @Signature( type = , method = "query", args = {, , , , , } )}) public class AuthInterceptor implements Interceptor { private static final Map<Class<?>, Map<String, List<List<Class>>>> mapperCache = new ConcurrentHashMap(); @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = (); String id = ((MappedStatement)args[0]).getId(); String clazzName = (0, ('.')); String mapperMethod = (('.') + 1); Object[] paramArr = getParamArr(args[1]); Class<?> clazz = (clazzName); Method method = getMethod(clazz, mapperMethod, paramArr); AuthFilter authFilter = (); // If the method does not add annotation, execute normally, otherwise start parsing if (authFilter != null) { Map params = new HashMap(); // Get each filed String orgFiled = (); String userFiled = (); // Get the user login id and organization ID String orgId = (); String loginId = (); boolean ignoreOrgFiled = (); boolean ignoreUserFiled = (); MappedStatement ms = (MappedStatement)args[0]; Object parameter = args[1]; BoundSql boundSql; if ( == 4) { boundSql = (parameter); } else { boundSql = (BoundSql)args[5]; } String sql = (); // Add organization number if (!ignoreOrgFiled) { if((orgId)){ (orgFiled , orgId); }else { throw new IllegalStateException("The user is not logged in!"); } } if (!ignoreUserFiled) { if((loginId)){ (userFiled , loginId); }else { throw new IllegalStateException("The user is not logged in!"); } } if(() > 0){ String concatSql = contactConditions(wrapSql(sql) , params); ("Addedsqlfor: {}" , concatSql); (boundSql, "sql", concatSql); } } return (); } @Override public Object plugin(Object target) { return (target, this); } @Override public void setProperties(Properties properties) { } private String wrapSql(String sql){ if((sql)){ StringBuilder realSql = new StringBuilder(); ("select * from ( "); (sql); (") a"); return (); } return sql; } /** Get the corresponding Method reflection class of mapper */ private Method getMethod(Class<?> clazz, String mapperMethod, Object[] paramArr) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { // 1. Check the mapper interface cache if (!(clazz)) // Mapper does not have cache, so it is cached { cacheMapper(clazz); } // 2. Return to the corresponding method A: for (List<Class> paramList : (clazz).get(mapperMethod)) { if (!()) { for (int i = 0; i < ; i++) { // Compare parameter list class if (paramArr[i] != null) if (!compareClass((i), paramArr[i].getClass())) continue A; } return (mapperMethod, (new Class[()])); } } return (mapperMethod); // Return to the method without parameters } /** Cache mapper method fields */ private void cacheMapper(Class<?> clazz) { Map<String, List<List<Class>>> methodMap = new HashMap(); for(Method method : ()) { List<List<Class>> paramLists = (()) ? (()) : new ArrayList<List<Class>>(); List<Class> paramClass = new ArrayList<Class>(); for (Type type : ()) { ((Class) type); } (paramClass); ((), paramLists); } (clazz, methodMap); } /** class comparison */ private boolean compareClass(Class<?> returnType, Class<?> paramType) throws NoSuchFieldException, IllegalAccessException { if(returnType == paramType) { return true; } else if((paramType)) { // Determine whether paramType is a returnType subclass or implementation class return true; } // Basic data type judgment else if(()) { // paramType is the packaging class return returnType == ("TYPE").get(null); } else if(()) { // returnType is the wrapper class return paramType == ("TYPE").get(null); } return false; } /** * Get the parameter value of the parameter list of the mapper interface in mybatis * @param parameter * @return */ private Object[] getParamArr(Object parameter) { Object[] paramArr = null; // The mapper interface uses paramMap, passing multiple parameters if(parameter instanceof ) { Map map = ((Map) parameter); if(!()) { StringBuilder builder = new StringBuilder(); // Initialize param_arr int size = () >> 1; paramArr = new Object[size]; for(int i = 1;i <= size;i ++) { // Use param0 ~ paramN to name parameters in the mapper interface paramArr[i - 1] = (("param").append(i).toString()); (0); } } } else if(parameter != null) { paramArr = new Object[1]; paramArr[0] = parameter; } return paramArr; } private static String contactConditions(String sql, Map<String, Object> columnMap) { SQLStatementParser parser = (sql, ); List<SQLStatement> stmtList = (); SQLStatement stmt = (0); if (stmt instanceof SQLSelectStatement) { StringBuffer constraintsBuffer = new StringBuffer(); Set<String> keys = (); Iterator<String> keyIter = (); if (()) { String key = (); (key).append(" = " + getSqlByClass((key))); } while (()) { String key = (); (" AND ").append(key).append(" = " + getSqlByClass((key))); } SQLExprParser constraintsParser = ((), ); SQLExpr constraintsExpr = (); SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; // Get SQLSelect SQLSelect sqlselect = (); SQLSelectQueryBlock query = (SQLSelectQueryBlock) (); SQLExpr whereExpr = (); // Modify where expression if (whereExpr == null) { (constraintsExpr); } else { SQLBinaryOpExpr newWhereExpr = new SQLBinaryOpExpr(whereExpr, , constraintsExpr); (newWhereExpr); } (query); return (); } return sql; } private static String getSqlByClass(Object value){ if(value instanceof Number){ return value + ""; }else if(value instanceof String){ return "'" + value + "'"; } return "'" + () + "'"; } }
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.