Mybatis-Plus 学习以及实践
简介
参考网址
开发环境
开始开发
- 配置 pom.xml
- Dao/Service/Entity
- 基本方法
- 查询类
- 更新类
分页插件
- pom.xml
- 代码示例
生成代码
- pom.xml
- 代码
乐观锁插件
- 配置
- 说明
Demo
Mybatis-Plus 学习以及实践
简介
即对 Mybatis 进行了增强, 结合了 Hiberante 的类型, 封装了一些单表的操作, 可以对进行单表的操作不需要写一些 sql, 直接上手开发, 加快了开发效率, 不过同时也会造成访问数据库的代码混杂的情况, 有利有弊.
参考网址
官网文档 https://mp.baomidou.com/guide/ , 官方文档.
开发环境
- Eclipse
- java8
- SpringBoot + maven
开始开发
这里只是配置运行一下简单的 Mybatis-plus 项目, 试验的对象只有一张表, 完成对齐的 CURD.
初始化一个 SpringBoot 或者复制 SpringBoot 项目, 初始化的时候可以去 springBoot 提供的网址进行初始化 Spring Initializr https://start.spring.io/
配置 pom.xml
- <!-- mybatis-plus -->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-generator</artifactId>
- <version>3.2.0</version>
- </dependency>
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.2.0</version>
- </dependency>
- <!-- mysql -->
- <dependency>
- <groupId>MySQL</groupId>
- <artifactId>MySQL-connector-java</artifactId>
- <version>8.0.13</version>
- <scope>runtime</scope>
- </dependency>
- Dao/Service/Entity
生成 Entity, 基本的 Entity 和 Mybatis 的一致, 有个主键的注解可以注意下, 影响不大.
Mapper 里面不需要添加其他内容, 新建一个空的 class, 然后继承 BaseMapper 即可
public interface ByReconcileDepartMapper extends BaseMapper<ByReconcileDepart>{}
Service 也不需要添加, 继承 IService
public interface IByReconcileDepartService extends IService<ByReconcileDepart> {}
ServiceImpl 也不需要添加, 需要继承 ServiceImpl, 实现 IByReconcileDepartService, 注解为 @Service
public class ByReconcileDepartServiceImpl extends ServiceImpl<ByReconcileDepartMapper, ByReconcileDepart> implements IByReconcileDepartService {}
到这里一个表的对应的实体, service,mapper 已经构建完成, 还是非常方便的, 代码也看起来挺简洁.
基本方法
这里只介绍一下常用的几个方法, 详细的介绍需要自行去官网查看.
因为 Mapper 和 Service 继承的父类中已经默认实现了基础方法, 基本包含了单表的 CURD, 这里直接使用, 不需要添加其他代码.
查询类
提供了条件构造器 QueryWrapper, 即条件构造, 基本的使用方法为 allEq,eq 等, 使用方式基本为先构造一个条件构造器 Wrapper, 然后赋给其条件, 但条件为 key-value, 多条件为 Map,List. 然后将其当做参数传递给指定的查询方法.
多个条件查询
- @Test
- public void listByMap() {
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("scenes_name", "大型自助机");
- Collection<ByReconcileDepart> listByMap = service.listByMap(map);
- System.out.println(listByMap);
- }
得到单个, 注意一下第二个参数影响如果查询出来多个会不会报错的问题
- @Test
- public void getOne() {
- HashMap<String,Object> map = new HashMap<String, Object>();
- map.put("scenes_name", "大型自助机");
- map.put("platform_mch_id","1540492611");
- map.put("seq",null);
- System.out.println(map);
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- // 第二个参数为是否关注 map 中为 null 的建, 默认为关注, 即会添加 seq is null, false 会剔除掉为 null 的键
- q.allEq(map,false);
- // 第二个参数为查询多个是否会报错, 默认为 true 会报错, 可手动指定为 false, 不会报错并且会返回一个
- ByReconcileDepart one = service.getOne(q,false);
- System.out.println(one);
- }
- Group By
- @Test
- public void listGroupBy() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- q.eq("scenes_name", "大型自助机");
- q.groupBy("platform_mch_id");
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
- Order By
- @Test
- public void listOrderBy() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- q.eq("scenes_name", "大型自助机");
- q.orderByDesc("scenes_name","platform_mch_id");
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
Or, 添加 Or 条件, 默认两个条件是用 and 连接, 只有手动调用 or 才会用 or, 例如下面如果不用条件则是 and 调用了则是 or
- @Test
- public void listOr() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- // 这里注意, 默认两个条件是用 and 连接, 只有手动调用 or 才会用 or, 例如下面如果不用条件则是 and 调用了则是 or
- q.eq("scenes_name", "大型自助机");
- q.or();
- q.eq("platform_mch_id", "1540492611");
- q.orderByDesc("scenes_name","platform_mch_id");
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
Or 嵌套, 1-2 层嵌套可以使用, 如果多层嵌套的话不推荐使用, 推荐使用手写 sql, 如果使用的话会增加后期的维护工作量.
- @Test
- public void listOrAnd() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- // 嵌套查询, where ( scenes_name = ? OR ( ( scenes_name = ? AND scenes_name = ? ) ) )
- q.eq("scenes_name", "大型自助机");
- q.or(i->i.eq("scenes_name", "1").eq("scenes_name", "大型"));
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
And 嵌套
- @Test
- public void listOrAnd2() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- // 嵌套查询, where ( scenes_name = ? AND ( ( scenes_name = ? AND scenes_name = ? ) ) )
- q.eq("scenes_name", "大型自助机");
- q.and(i->i.eq("scenes_name", "1").eq("scenes_name", "大型"));
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
apply 手动添加 Where 条件
- @Test
- public void listapply() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- // 手动拼接 sql 条件, 有两种形式, 一种为直接写死 sql, 一种使用占位符, 后面为可变参数 apply(String applySql, Object... params)
- q.apply("seq = 5");
- List<ByReconcileDepart> list = service.list(q);
- System.out.println(list);
- }
更新类
其中还提供了保存, 删除接口, 其使用方法比较简单, 可以根据官网或者自己点进去代码查看即可, 下面只介绍一下通过 UpdateWrapper 来进行更新的方式.
提供了条件构造器 UpdateWrapper, 其基本使用方法和 QueryWrapper 一致, 不过添加了 Set, 即设置需要更新的字段
- @Test
- public void updateWrapper() {
- // set 为设置 update set * 的内容, 设置 where 后面的内容和条件选择器一致
- UpdateWrapper<ByReconcileDepart> w = new UpdateWrapper<ByReconcileDepart>();
- w.eq("seq", 5);
- w.set("organization_code", "123");
- w.set("omg", "123");
- boolean update = service.update(w);
- System.out.println(update);
- }
分页插件
pom.xml
以前使用的是 pagehelper, 不过直接引用的话会有 jar 包冲突, 需要剔除一下 jar 即可.
- <!-- pagehelper 解决掉 jar 包冲突 -->
- <dependency>
- <groupId>com.GitHub.pagehelper</groupId>
- <artifactId>pagehelper-spring-boot-starter</artifactId>
- <version>1.2.5</version>
- <exclusions>
- <exclusion>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
代码示例
- @Test
- public void listPage() {
- QueryWrapper<ByReconcileDepart> q = new QueryWrapper<ByReconcileDepart>();
- q.eq("scenes_name", "大型自助机");
- // 可以整合 pagehandler, pom 文件注意剔除, getTotal 获取总条数, 注意配置文件的配置方式
- Page<ByReconcileDepart> startPage = PageHelper.startPage(5, 3);
- List<ByReconcileDepart> list = service.list(q);
- long total = startPage.getTotal();
- System.out.println(total);
- System.out.println(list.size());
- }
生成代码
pom.xml
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-generator</artifactId>
- <version>3.2.0</version>
- </dependency>
- <!-- 默认模板 pom -->
- <dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity-engine-core</artifactId>
- <version>2.1</version>
- </dependency>
注意 pom.xml 中添加对应的引擎引用
同时需要手动将 mybatis-plus-generator jar 包中的模板文件 copy 到自己的项目中, jar 包中的模板文件再 resource/template 中, 打开 jar 包方法为解压即可.
代码
官网的代码复制下来更改一下数据库连接, 就可以直接生成看一下结果, 正式用的话需要更改一下包名以及公共类型的代码.
这里全都是用的默认提供的生成规则, 如果需要自定义模板的话自己去官网查看
同时需要自己手动添加数据库驱动.
在这一步遇到了一个报错, The server time zone value, 即 JDBC 时区的问题, 引起的原因是 MySQL 驱动的版本过高, 解决办法为在数据库连接地址后面添加 serverTimezone=GMT+8, 或者降低版本 (N 多办法中的其中两个).
多层 or/and 嵌套推荐手写 sql,Mybatis-plus 只有在简单查询中好用, 复杂查询推荐手写 sql, 便于以后的修改.
乐观锁插件
原生的 Mybatis 如果需要启动乐观锁的话需要手动再 sql 中实现, 现在提供了内置的控制方法. 这样的话还是比较好用的, 虽然不如 Hinerbate 那样只能, 还是能解决一些方法.
配置
添加配置 Bean
@Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
对应的字段添加 @Version 注解
说明
仅支持 updateById(id) 与 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
newVersion 会回写到 entity 中
如果乐观锁冲突的话不会报错, 会返回 0, 这样就不如 Hibernate 好, Hibernate 会报出一个指定的错误, 这里只能根据返回的来做判断, 这样就不能判断是乐观锁冲突返回的 0, 还是因为不符合条件不能更新返回的 0.
乐观锁冲突出现后需要进行重试, 重新获取对象, 然后重新更新.
Demo
自己的学习 Demo 放到 demo-GitHub, 有需要的可以去看下, 具体的使用代码再 Test 内
来源: https://www.cnblogs.com/liyuhui-Z/p/11637584.html