1.引入依赖

  1. <dependency>
  2. <groupId>com.xy</groupId>
  3. <artifactId>xy-core-framework-dal-common</artifactId>
  4. <version>${xy-core-framework-dal-common.version}</version>
  5. </dependency>

提供了6个自定义注解

framework-dal-common - 图1

数据权限注解

TenantId(租户隔离),DeptId(部门ID),CreateBy(创建人)

强制选择主从数据源

ShardingMaster(强制走主库,可指定) ShardingOneSlave(强制从库,可指定)

2.设置DO类的权限注解

  1. @Data
  2. public class BaseEntity {
  3. /**
  4. * 主键
  5. */
  6. @TableId
  7. private Long id;
  8. /**
  9. * 创建人,添加注解可作为权限数据查询条件
  10. */
  11. @CreateBy(value = "create_by", type = "String")
  12. private String createBy;
  13. }
  1. @Data
  2. public class ExtendEntity extends BaseEntity {
  3. /**
  4. * 商户编码,添加注解可作为权限数据查询条件
  5. */
  6. @TenantId(value = "merchant_code", type = "String")
  7. private String merchantCode;
  8. /**
  9. * 部门ID,添加注解可作为权限数据查询条件
  10. */
  11. @DeptId(value = "dept_id", type = "Long")
  12. private Long deptId;
  13. }

3.实现权限数据加载

  1. /**
  2. * 数据权限加载
  3. * <p>双层map结构,第一层map的key为表名</p >
  4. * <p>第二层map的key为数据权限字段,目前二层key仅支持merchantCode,deptId,createBy</p >
  5. *
  6. * @author jack.li
  7. * @version 1.0
  8. * @date 2020/3/17 下午11:12
  9. */
  10. @Slf4j
  11. @Service("roleDataService")
  12. public class RoleDataServiceImpl implements RoleDataService {
  13. Map<String, Map<String, String>> columns = new HashMap<>();
  14. @Override
  15. public Map<String, Map<String, String>> tableColumns() {
  16. log.info("<<<<<<<<<<<<<<<<<<<<<<XXXXXXXXXXXXXXXXX>>>>>>>>>>>>>>>>>>>>>");
  17. Map<String, String> taskNotify = new HashMap<>();
  18. // taskNotify.put("merchantCode", "channel");
  19. // taskNotify.put("deptId", "dept");
  20. // taskNotify.put("createBy", "create_id");
  21. // columns.put("system_task_notify", taskNotify);
  22. return columns;
  23. }
  24. }

4.框架默认装配

4.1分页拦截器

单数据源情况下,需要指定db-type类型。多数据源情况下,一定不要指定db类型,分页查询最大行数为100,

  1. mybatis-plus.db-type=mysql
  2. mybatis-plus.max-limit=100

4.2数据权限

只需实现步骤3,便会动态修改查询条件

4.3乐观锁

表结构定义中需要version版本号字段,更新时候将查询到的version设置到更新条件即可

4.4全局更新,删除禁止组件

对于无条件的更新,删除操作,会自动禁止sql执行.

4.5sql性能插件

建议在开发,测试环境开启,对于性能较差的sql,会跑出异常。例如!=,not in等操作,默认关闭。

  1. mybatis-plus.illegal-s-q-l-inner-interceptor=true

5.数据权限底层实现说明(开发无需关心)

5.1自定义XyDataPermissionHandler接口

通过XyDataPermissionHandler获取mybaits-plus中的查询条件Expression

  1. public interface XyDataPermissionHandler {
  2. /**
  3. * 获取数据权限 SQL 片段
  4. *
  5. * @param where 待执行 SQL Where 条件表达式
  6. * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
  7. * @return JSqlParser 条件表达式
  8. */
  9. Expression getSqlSegment(Expression where, String mappedStatementId, Select select);
  10. }

5.2自定义XyJsqlParserSupport sql解析

在processSelect方法中,通过XyDataPermissionHandler改变动态查询条件

  1. @Slf4j
  2. @Data
  3. @NoArgsConstructor
  4. @AllArgsConstructor
  5. public class XyJsqlParserSupport extends JsqlParserSupport implements InnerInterceptor {
  6. private XyDataPermissionHandler dataPermissionHandler;
  7. @Override
  8. public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  9. log.info("---------beforeQuery start----------------");
  10. /*
  11. String sql = boundSql.getSql();
  12. if (!boundSql.hasAdditionalParameter("merchant_code")) {
  13. JwtUser userInfo = UserUtils.getUserInfo();
  14. if (!Objects.isNull(userInfo)) {
  15. boundSql.setAdditionalParameter("merchant_code", userInfo.getMerchantCode());
  16. }
  17. }
  18. PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
  19. mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
  20. */
  21. log.info("---------beforeQuery end:{}----------------", boundSql.getSql());
  22. }
  23. @Override
  24. public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
  25. log.info("---------beforePrepare----------------");
  26. }
  27. @Override
  28. protected void processInsert(Insert insert, int index, String sql, Object obj) {
  29. super.processInsert(insert, index, sql, obj);
  30. log.info("---------processInsert----------------");
  31. }
  32. @Override
  33. protected void processDelete(Delete delete, int index, String sql, Object obj) {
  34. super.processDelete(delete, index, sql, obj);
  35. log.info("---------processDelete----------------");
  36. }
  37. @Override
  38. protected void processUpdate(Update update, int index, String sql, Object obj) {
  39. super.processUpdate(update, index, sql, obj);
  40. log.info("---------processUpdate----------------");
  41. }
  42. @Override
  43. protected void processSelect(Select select, int index, String sql, Object obj) {
  44. PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
  45. Table table = (Table) plainSelect.getFromItem();
  46. String name = table.getName();
  47. log.info("---------processSelect---op table name :{}-------------", name);
  48. Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), (String) obj, select);
  49. if (null != sqlSegment) {
  50. plainSelect.setWhere(sqlSegment);
  51. }
  52. log.info("---------processSelect----------------");
  53. }
  54. }

6.属性填充

框架默认提供MetaObjectHandler,对inser,update操作的创建人,创建时间,更新人,更新时间进行自动填充。

如果项目自定义了自己的MetaObjectHandler,可以通过@Primary注解选当前项目自定义的MetaObjectHandler