一、MyBatis vs JPA
1、MyBatis优势
(1)自由控制 SQL语句,可手动优化SQL语句
(2)SQL与代码分离,写在xml文件中,或者注解中
(3)提供xml标签,支持编写动态SQL语句
2、JPA的优势(Java Persistence API)
(1)Spring Data JPA对JPA的再次封装(底层使用Hibernate),使用JPQL语句,移植性比较好,数据库变更方便,面向对象的操作更易上手
(2)提供了很多的CRUD方法,开发效率高
3、MyBatis劣势
(1)需要手写SQL语句(逆向工程可自动生成实体类、mapper文件,含有大量SQL语句)
(2)xml文件中有大量的SQL要维护,日积月累变得难以维护
二、MyBatis-Plus简介
MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。框架结构,特性,支持数据库
简单开始:
建库建表->引入依赖->配置(application.properties)->编码->测试
三、SSM传统编程模式
Dao层的接口中写抽象方法->XML或注解里写SQL->Service中调用Dao层的接口->Controller中调用Service方法
四、MP的通用Mapper
BaseMapper<T>
常用注解:(其中可在application.properties中设置表名前缀,全库的表都是这个前缀)
数据库表名:@TableName("value")// 表名的映射设置
数据库字段名:@TableId("value")// 主键字段的映射设置
数据库字段名:@TableField("value")// 普通字段的映射设置
排除非表字段的三种方式:(数据库表中没有此字段,但又想暂时存储某个数据,实体类冗余属性的解决方案)
1)使用transient关键字,不参与序列化过程
2)标注static静态属性,lombok不会为静态属性添加get/set方法,需要手动添加
3)使用注解:@TableField(exist=false)// 代表数据库中不存在此注解修饰的字段
五、MP的查询(Retrieve)
T selectById(Serializable id);// 根据ID查询
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);// 根据ID批量查询
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);// 根据columnMap条件查询
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据entity条件查询一条记录,如果逻辑非唯一该方法不会自动替您 limit 1,需用wrapper.last("limit 1") 设置唯一性。
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询总记录数
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录,实体对象封装操作类(可以为 null)
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录,注意: 只返回第一个字段的值
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录(并翻页)
String str = "2019-12-12"; queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}",str).inSql("field","sqlstr")
name like '王%' and (age<40 or email is not null)------>queryWrapper.likeRight("name","王").and(wq->wq.lt("age",40).or().isNotNull("email")); // and方法可以传入lambda表达式,用来表示括号的作用
condition条件控制是否加入查询条件中,注意,如果都不加入条件,没有where语句是会查询所有数据的
name 和 email 都为空的时候,是否会出现查询所有的情况?
讲师回答 / 老猿你是指queryWrapper.like(StringUtils.isNotEmpty(name), "name", name).like(StringUtils.isNotEmpty(email), "email", email)这句,如果name 和 email 都为空都为空的情况吗?如果是的话,两个都为空,是没有where条件的,就会查询所有记录。
复杂查询:
使用Wapper作为条件构造器;
AbstractWrapper
说明:QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
使用实体类作为条件构造器
默认---->属性不为空的值作为where的条件,默认---->使用等号连接
如果的like的需求,需要在实体类的属性上添加注解@TableField(condition=SqlCondition.LIKE)// 也可自定义condition模仿他的形式
使用Lambda表达式作为条件构造器
作用:防误写,需要使用new LambdaQueryChainWrapper<T>(BaseMapper)或者Wappers.<T>lambdaQuery
从likeRight("name","王")变为likeRight(User::getName,"王"),再也不用担心写错Name字段名了
六、自定义SQL
原生MyBatis:注解形式和xml形式
需求来源:在使用了mybatis-plus之后, 自定义SQL的同时也想使用Wrapper的便利应该怎么办? 在mybatis-plus版本3.0.7得到了完美解决 版本需要大于或等于3.0.7, 以下两种方案取其一即可
七、MP更新和删除
int updateById(@Param(Constants.ENTITY) T entity);
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
int deleteById(Serializable id);
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
八、AR模式(ActiveRecord)
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
继承Model类,使用lombok会报警告,@EqualsAndHashCode(callSuper=false)便可消除警告
user.setCreateTime(LocalDateTime.now());
九、MP主键策略
局部策略:@TableId(type=IdType.ID_WORKER_STR)
全局策略:配置文件中设置->mybatis-plus.global-config.id-type:
auto;id-worker;id-worker-str;input;none;uuid
支持的主键策略:数据库自增,雪花算法,UUID
十、通用Service
Dao-----Mapper接口(BaseMapper,自动)
Service-----通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类MP的-----ServiceImpl是什么作用
十一、MP的代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖