1.引入依赖
<dependency><groupId>com.xy</groupId><artifactId>xy-core-framework-dal-common</artifactId><version>${xy-core-framework-dal-common.version}</version></dependency>
提供了6个自定义注解

数据权限注解
TenantId(租户隔离),DeptId(部门ID),CreateBy(创建人)
强制选择主从数据源
ShardingMaster(强制走主库,可指定) ShardingOneSlave(强制从库,可指定)
2.设置DO类的权限注解
@Datapublic class BaseEntity {/*** 主键*/@TableIdprivate Long id;/*** 创建人,添加注解可作为权限数据查询条件*/@CreateBy(value = "create_by", type = "String")private String createBy;}
@Datapublic class ExtendEntity extends BaseEntity {/*** 商户编码,添加注解可作为权限数据查询条件*/@TenantId(value = "merchant_code", type = "String")private String merchantCode;/*** 部门ID,添加注解可作为权限数据查询条件*/@DeptId(value = "dept_id", type = "Long")private Long deptId;}
3.实现权限数据加载
/*** 数据权限加载* <p>双层map结构,第一层map的key为表名</p >* <p>第二层map的key为数据权限字段,目前二层key仅支持merchantCode,deptId,createBy</p >** @author jack.li* @version 1.0* @date 2020/3/17 下午11:12*/@Slf4j@Service("roleDataService")public class RoleDataServiceImpl implements RoleDataService {Map<String, Map<String, String>> columns = new HashMap<>();@Overridepublic Map<String, Map<String, String>> tableColumns() {log.info("<<<<<<<<<<<<<<<<<<<<<<XXXXXXXXXXXXXXXXX>>>>>>>>>>>>>>>>>>>>>");Map<String, String> taskNotify = new HashMap<>();// taskNotify.put("merchantCode", "channel");// taskNotify.put("deptId", "dept");// taskNotify.put("createBy", "create_id");// columns.put("system_task_notify", taskNotify);return columns;}}
4.框架默认装配
4.1分页拦截器
单数据源情况下,需要指定db-type类型。多数据源情况下,一定不要指定db类型,分页查询最大行数为100,
mybatis-plus.db-type=mysqlmybatis-plus.max-limit=100
4.2数据权限
只需实现步骤3,便会动态修改查询条件
4.3乐观锁
表结构定义中需要version版本号字段,更新时候将查询到的version设置到更新条件即可
4.4全局更新,删除禁止组件
对于无条件的更新,删除操作,会自动禁止sql执行.
4.5sql性能插件
建议在开发,测试环境开启,对于性能较差的sql,会跑出异常。例如!=,not in等操作,默认关闭。
mybatis-plus.illegal-s-q-l-inner-interceptor=true
5.数据权限底层实现说明(开发无需关心)
5.1自定义XyDataPermissionHandler接口
通过XyDataPermissionHandler获取mybaits-plus中的查询条件Expression
public interface XyDataPermissionHandler {/*** 获取数据权限 SQL 片段** @param where 待执行 SQL Where 条件表达式* @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法* @return JSqlParser 条件表达式*/Expression getSqlSegment(Expression where, String mappedStatementId, Select select);}
5.2自定义XyJsqlParserSupport sql解析
在processSelect方法中,通过XyDataPermissionHandler改变动态查询条件
@Slf4j@Data@NoArgsConstructor@AllArgsConstructorpublic class XyJsqlParserSupport extends JsqlParserSupport implements InnerInterceptor {private XyDataPermissionHandler dataPermissionHandler;@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {log.info("---------beforeQuery start----------------");/*String sql = boundSql.getSql();if (!boundSql.hasAdditionalParameter("merchant_code")) {JwtUser userInfo = UserUtils.getUserInfo();if (!Objects.isNull(userInfo)) {boundSql.setAdditionalParameter("merchant_code", userInfo.getMerchantCode());}}PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));*/log.info("---------beforeQuery end:{}----------------", boundSql.getSql());}@Overridepublic void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {log.info("---------beforePrepare----------------");}@Overrideprotected void processInsert(Insert insert, int index, String sql, Object obj) {super.processInsert(insert, index, sql, obj);log.info("---------processInsert----------------");}@Overrideprotected void processDelete(Delete delete, int index, String sql, Object obj) {super.processDelete(delete, index, sql, obj);log.info("---------processDelete----------------");}@Overrideprotected void processUpdate(Update update, int index, String sql, Object obj) {super.processUpdate(update, index, sql, obj);log.info("---------processUpdate----------------");}@Overrideprotected void processSelect(Select select, int index, String sql, Object obj) {PlainSelect plainSelect = (PlainSelect) select.getSelectBody();Table table = (Table) plainSelect.getFromItem();String name = table.getName();log.info("---------processSelect---op table name :{}-------------", name);Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), (String) obj, select);if (null != sqlSegment) {plainSelect.setWhere(sqlSegment);}log.info("---------processSelect----------------");}}
6.属性填充
框架默认提供MetaObjectHandler,对inser,update操作的创建人,创建时间,更新人,更新时间进行自动填充。
如果项目自定义了自己的MetaObjectHandler,可以通过@Primary注解选当前项目自定义的MetaObjectHandler
