迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:mybatis-plus-ext开源软件地址:https://gitee.com/tangzc/mybatis-plus-ext开源软件介绍:简介
前言如果感觉框架对您有所帮助,请给个小星星⭐️,作者二线不知名小公司码农一枚,欢迎来撩共同进步。「二维码看不到的查看项目文档下"微信.png"」 原理介绍 基于注解的形式,将日常工作中重复的模板式代码进行了封装,底层实现完全调用的Mybatis-Plus的框架,全都是走的单表查询的方式,所以不用担心数据库兼容问题(自动建表功能除外,只支持mysql),同样也不需要担心性能问题(前提是正确使用[捂脸]),因为框架内部会自动做查询整合。 快速开始引入jar包
<!-- !!!重点说明,框架内部已经引入了MybatisPlus的包,自己项目中的需要去掉!!! --><!-- 全功能整体引入 --><dependency> <groupId>com.tangzc</groupId> <artifactId>mybatis-plus-ext-boot-starter</artifactId> <version>{maven仓库搜索最新版}</version></dependency><!-- 如果想只引入自动建表 --><dependency> <groupId>com.tangzc</groupId> <artifactId>mybatis-plus-ext-actable-core</artifactId> <version>{maven仓库搜索最新版}</version></dependency><!-- 如果想只引入关联查询 --><dependency> <groupId>com.tangzc</groupId> <artifactId>mybatis-plus-ext-bind</artifactId> <version>{maven仓库搜索最新版}</version></dependency><!-- 如果想只引入数据冗余(关联更新) --><dependency> <groupId>com.tangzc</groupId> <artifactId>mybatis-plus-ext-datasource</artifactId> <version>{maven仓库搜索最新版}</version></dependency><!-- 如果想只引入动态条件 --><dependency> <groupId>com.tangzc</groupId> <artifactId>mybatis-plus-ext-condition</artifactId> <version>{maven仓库搜索最新版}</version></dependency> 自动建表
@Data// @Table标记的可被识别为需要自动创建表的Entity@Table(comment = "用户")public class User { // 自动识别id属性名为主键 // @IsAutoIncrement声明为自增主键,什么都不声明的话,默认为雪花算法的唯一主键(MP的自带功能),推荐默认便于后期的数据分布式存储等处理。 @IsAutoIncrement // 字段注释、类型、长度。@Column的所有属性均有独立的注解对应,具体请参照后面的注解介绍 @Column(comment = "主键", type = MySqlTypeConstant.BIGINT, length = 32) private String id; // 索引 @Index // 非空 @IsNotNull @ColumnComment("名字") private String name; // 唯一索引 @Unique // 非空 @IsNotNull @ColumnComment("手机号") private String phone; // 省略其他属性 ......} // 启用自动生成数据库表功能,此处简化了A.CTable的复杂配置,均采用默认配置@EnableAutoTable@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }} # actable的配置信息保留了如下几项,均做了默认配置,正常无需配置actable.table.auto=updateactable.model.pack=[Spring启动类所在包]actable.database.type=mysqlactable.index.prefix=自己定义的索引前缀#该配置项不设置默认使用actable_idx_actable.unique.prefix=自己定义的唯一约束前缀#该配置项不设置默认使用actable_uni_ 数据填充
@Data@Table(comment = "文章")public class Article { // 字符串类型的ID,默认也是雪花算法的一串数字(MP的默认功能) @ColumnComment("主键") private String id; @ColumnComment("标题") private String title; @ColumnComment("内容") private String content; // 文章默认激活状态 @DefaultValue("ACTIVE") @ColumnComment("内容") // ActicleStatusEnum(ACTIVE, INACTIVE) private ActicleStatusEnum status; @ColumnComment("发布时间") // 插入数据时候会自动获取系统当前时间赋值,支持多种数据类型,具体可参考@OptionDate注解详细介绍 @InsertOptionDate private Date publishedTime; @ColumnComment("发布人") // 插入的时候,根据UserIdAutoFillHandler自动填充用户id @InsertOptionUser(UserIdAutoFillHandler.class) private String publishedUserId; @ColumnComment("发布人名字") // 插入的时候,根据UserIdAutoFillHandler自动填充用户名字 @InsertOptionUser(UsernameAutoFillHandler.class) private String publishedUsername; @ColumnComment("最后更新时间") // 插入和更新数据时候会自动获取系统当前时间赋值,支持多种数据类型,具体可参考@OptionDate注解详细介绍 @InsertUpdateOptionDate private Date publishedTime; @ColumnComment("最后更新人") // 插入和更新的时候,根据UserIdAutoFillHandler自动填充用户id @InsertUpdateOptionUser(UserIdAutoFillHandler.class) private String publishedUserId; @ColumnComment("最后更新人名字") // 插入和更新的时候,根据UserIdAutoFillHandler自动填充用户名字 @InsertUpdateOptionUser(UsernameAutoFillHandler.class) private String publishedUsername;} /** * 全局获取用户ID * 此处实现IOptionByAutoFillHandler接口和AutoFillHandler接口均可,建议实现IOptionByAutoFillHandler接口, * 因为框架内的BaseEntity默认需要IOptionByAutoFillHandler的实现。后面会讲到BaseEntity的使用。 */@Componentpublic class UserIdAutoFillHandler implements IOptionByAutoFillHandler<String> { /** * @param object 当前操作的数据对象 * @param clazz 当前操作的数据对象的class * @param field 当前操作的数据对象上的字段 * @return 当前登录用户id */ @Override public String getVal(Object object, Class<?> clazz, Field field) { RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); // 配合网关或者过滤器,token校验成功后就把用户信息塞到header中 return request.getHeader("user-id"); }} /** * 全局获取用户名 */@Componentpublic class UsernameAutoFillHandler implements AutoFillHandler<String> { /** * @param object 当前操作的数据对象 * @param clazz 当前操作的数据对象的class * @param field 当前操作的数据对象上的字段 * @return 当前登录用户id */ @Override public String getVal(Object object, Class<?> clazz, Field field) { RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); // 配合网关或者过滤器,token校验成功后就把用户信息塞到header中 return request.getHeader("user-name"); }} 关联查询
@Data@Table(comment = "角色信息")public class Role { @ColumnComment("主键") private String id; @ColumnComment("角色名") private String name;} @Data@Table(comment = "用户信息")public class User { @ColumnComment("主键") private String id; @ColumnComment("用户名") private String username; @ColumnComment("密码") private String password; // 关键配置,声明了User想关联对应的Rule集合,中间表是UserRule @BindEntityByMid(conditions = @MidCondition( midEntity = UserRole.class, selfMidField = "userId", joinMidField = "roleId" )) private List<Role> roles;} @Data@Table(comment = "用户-角色关联关系")public class UserRole { @ColumnComment("主键") private String id; @ColumnComment("用户id") private String userId; @ColumnComment("角色id") private String roleId;} /** * 用户服务 */@Slf4j@Servicepublic class UserService { // UserRepository继承了BaseRepository<UserMapper, User>,后面会讲BaseRepository @Resource private UserRepository userRepository; /** * 根据用户的名字模糊查询所有用户的详细信息 */ @Transactional(readOnly = true) public List<UserDetailWithRoleDto> searchUserWithRuleByName(String name) { // MP的lambda查询方式 List<User> userList = userRepository.lambdaQuery() .eq(name != null, User::getUsername, name) .list(); // 关键步骤,指定关联角色数据。如果你打开sql打印,会看到3条sql语句,第一条根据id去User表查询user信息,第二条根据userId去UserRule中间表查询所有的ruleId,第三条sql根据ruleId集合去Rule表查询全部的权限 // 用法一、指定属性关联。 Binder.bindOn(userList, User::getRoles); // 用法二、全关联。此种用法默认关联user下所有声明需要绑定的属性 // Binder.bind(userList); return UserMapping.MAPPER.toDto5(userList); } /** * 根据用户的名字模糊查询所有用户的详细信息,等价于上一个查询方式 */ @Transactional(readOnly = true) public List<UserDetailWithRoleDto> searchUserWithRuleByName2(String name) { // 本框架拓展的lambda查询器lambdaQueryPlus,增加了bindOne、bindList、bindPage // 显然这是一种更加简便的查询方式,但是如果存在多级深度的关联关系,此种方法就不适用了,还需要借助Binder List<User> userList = userRepository.lambdaQueryPlus() .eq(name != null, User::getUsername, name) // 用法一、指定属性关联。 .bindList(User::getRoles); // 用法二、全关联。 // .bindList(); return UserMapping.MAPPER.toDto5(userList); }} ==提示==: 假如存在此种场景: // 数据库查询出了用户列表 【1】List<User> userList = userRepository.list();// 为所有用户关联角色信息 【2】Binder.bindOn(userList, User::getRoles);// 为所有角色信息关联菜单信息 【3】// Deeper为一个深度遍历工具,可以深入到对象的多层属性内部,从而获取全局上该层级的所有对象同一属性Binder.bindOn(Deeper.with(userList).inList(User::getRoles), Role::getMenus); 注意 |
请发表评论