Table of Contents
一、全局配置文件:applicationContext.xml
二、常用注解:
三、通用的CRUD:继承baseMapper
四、条件构造器:EntityWrapper 和 Condition
五、ActiveRecord(活动记录)
六、代码生成器
七、插件
1 分页插件:com.baomidou.mybatisplus.plugins.PaginationInterceptor
2 执行分析插件:com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
3性能分析插件:com.baomidou.mybatisplus.plugins.PerformanceInterceptor
4 乐观锁插件:com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor
八、自定义全局操作
九、公共字段自动填充
十、Oracle 主键 Sequence
代码地址:[email protected]:kathrinacathy/mybatisAndmybatisPlus.git
MyBatis-Plus(简称 MP),是一个 MyBatis 的增强工具包,只做增强不做改变. 为简化开 发工作、提高生产率而生 我们的愿景是成为 Mybatis 最好的搭档;
官方地址:
http://mp.baomidou.com
代码发布地址:
Github: https://github.com/baomidou/mybatis-plus
Gitee: https://gitee.com/baomidou/mybatis-plus
文档发布地址:
http://mp.baomidou.com/#/?id=%E7%AE%80%E4%BB%8B
集成mp就是将之前mabatis改为用:com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean 这个就可以
@TableName 映射表名
@TableField 映射字段名,也可以添加指定是否属于表中字段
@TableId 可以指定主键策略
@KeySequence(value = "seq_user",clazz=Integer.class) 指定oracle的序列
@Version 用于注解实体字段,必须要有 乐观锁插件
@Mapper :在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类
如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用@MapperScan
@MapperScan
作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类
// insert方法在插入时, 会根据实体类的每个属性进行非空判断,只有非空的属性对应的字段才会出现到SQL语句中
//Integer result = employeeMapper.insert(employee);
//insertAllColumn方法在插入时, 不管属性是否非空, 属性所对应的字段都会出现到SQL语句中.
更新
Integer updateById(@Param("et") T entity);
Integer updateAllColumnById(@Param("et") T entity)
查询
1)T selectById(Serializable id);
2) T selectOne(@Param("ew") T entity);
3) List
4) List
5) List
删除
1) Integer deleteById(Serializable id);
2) Integer deleteByMap(@Param("cm") Map
3) Integer deleteBatchIds(List extends Serializable> idList);
1) Mybatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者
Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担,
能够有效提高开发效率
2) 实体包装器,主要用于处理 sql 拼接,排序,实体参数查询等
3) 注意: 使用的是数据库字段,不是 Java 属性!
MP: EntityWrapper Condition 条件构造器
new EntityWrapper
Condition.create() .eq("email", "[email protected]")
@Test
public void testPaginationInterceptor() {
Page page = new Page(2, 5);
List resultList = mapper.selectPage(page, Condition.create().eq("email", "[email protected]"));
System.out.println(resultList);
System.out.println(page.getRecords());
System.out.println("当前页"+page.getCurrent());
System.out.println("总页数"+page.getPages());
System.out.println("每页多少条"+page.getSize());
System.out.println("总共多少条"+page.getTotal());
System.out.println("是否有上一页"+page.hasPrevious());
//添加分页插件后com.baomidou.mybatisplus.plugins.PaginationInterceptor
// SELECT id,last_name AS lastName,gender,email,emp_status AS empStatus FROM tb_employee WHERE (email = ?) LIMIT 5,5 代表第二页
}
AR模式(ActiveRecord)简单的说就是直接用实体操作数据库。
仅仅需要让实体类继承 Model 类且实现主键指定方法,即可开启 AR 之旅.需要写mapper接口,不然会报错
@TableName("tbl_employee")
public class Employee extends Model
// .. fields
// .. getter and setter
@Override
protected Serializable pkVal() {
return this.id; }
AR基本的CRUD
1) 插入操作
public boolean insert()
2) 修改操作
public boolean updateById()
3) 查询操作
public T selectById()
public T selectById(Serializable id)
public List
public List
public int selectCount(Wrapper wrapper)
4) 删除操作
public boolean deleteById()
public boolean deleteById(Serializable id)
public boolean delete(Wrapper wrapper)
5) 分页复杂操作
public Page
示例:
/**
* AR 查询
*/
@Test
public void testSelect () {
Employee employee = new Employee();
// employee.setId(1017);
// Employee employee1 = employee.selectById();
// System.out.println(employee1);
//
//
// Employee employee2 = employee.selectById(166);
// System.out.println(employee2);
// List employees = employee.selectAll();
// System.out.println(employees);
List email = employee.selectList(new EntityWrapper().eq("email", "@"));
System.out.println(email);
int i = employee.selectCount(new EntityWrapper().like("last_name", "a"));
System.out.println(i);
}
模板引擎
MP 的代码生成器默认使用的是 Apache 的 Velocity 模板,当然也可以更换为别的模板
技术,例如 freemarker。此处不做过多的介绍。
需要加入 Apache Velocity 的依赖
加入 slf4j ,查看日志输出信息
org.apache.velocity
velocity-engine-core
2.0
org.slf4j
slf4j-api
1.7.7
org.slf4j
slf4j-log4j12
1.7.25
org.springframework
spring-webmvc
4.3.10.RELEASE
编写执行代码生成的代码:
//1 全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setActiveRecord(true)
.setAuthor("kathrina")
.setOutputDir("G:\\ideaIU-2018.1.4.win\\IdeaProjects\\mybatisPlus\\src\\main\\java")
.setFileOverride(true)
.setIdType(IdType.AUTO)
.setServiceName("%sService") //设置生成的service接口的名字的首字母是否为I
.setBaseResultMap(true)
.setBaseColumnList(true);//生成sql片段
//2 数据库配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
.setUrl("jdbc:mysql://192.168.163.131:3307/mybatis?allowMultiQueries=true")
.setUsername("root")
.setPassword("root");
//3 策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setCapitalMode(true) //全局大写命名
.setDbColumnUnderline(true) // 指定表名 字段名是否使用下划线
.setNaming(NamingStrategy.underline_to_camel) // 数据库表映射到实体的命名策略
.setTablePrefix("tb_")
.setInclude("tb_dept"); // 生成的表
//4 包名策略
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("com.mybatisPlus")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("entity")
.setXml("mapper");
//整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(globalConfig)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(pkConfig);
//6. 执行
ag.execute();
插件机制: Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求,完
成相关数据的动态改变。
Executor
StatementHandler
ParameterHandler
ResultSetHandler
2) 插件原理
四大对象的每个对象在创建时,都会执行 interceptorChain.pluginAll(),会经过每个插
件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四
大对象相关方法的执行,因为要执行四大对象的方法需要经过代理.
该插件的作用是分析 DELETE UPDATE 语句,防止小白或者恶意进行 DELETE UPDATE 全表操作
1 性能分析拦截器,用于输出每条 SQL 语句及其执行时间
2 SQL 性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题
@Version 用于注解实体字段,必须要有
private ApplicationContext ioc
= new ClassPathXmlApplicationContext("applicationContext.xml");
private EmployeeMapper mapper = ioc.getBean("employeeMapper",EmployeeMapper.class);
private DeptMapper deptMapper = ioc.getBean("deptMapper",DeptMapper.class);
@Test
public void testPaginationInterceptor() {
Page page = new Page(2, 5);
List resultList = mapper.selectPage(page, Condition.create().eq("email", "[email protected]"));
System.out.println(resultList);
System.out.println(page.getRecords());
System.out.println("当前页"+page.getCurrent());
System.out.println("总页数"+page.getPages());
System.out.println("每页多少条"+page.getSize());
System.out.println("总共多少条"+page.getTotal());
System.out.println("是否有上一页"+page.hasPrevious());
//添加分页插件后com.baomidou.mybatisplus.plugins.PaginationInterceptor
// SELECT id,last_name AS lastName,gender,email,emp_status AS empStatus FROM tb_employee WHERE (email = ?) LIMIT 5,5 代表第二页
}
@Test
public void testSqlExplainInterceptor() {
mapper.delete(null); // 全表删除
}
@Test
public void testPerformanceInterceptor() {
// Time:1199 ms - ID:com.mybatisPlus.mapper.EmployeeMapper.selectList
// Execute SQL:
// SELECT
// id,
// last_name AS lastName,
// gender,
// email,
// emp_status AS empStatus
// FROM
// tb_employee]
List employees = mapper.selectList(null);
System.out.println(employees);
}
@Test
public void testOptimisticLockerInterceptor() {
Dept dept = new Dept();
dept.setId(1);
dept.setDetpName("开发部");
dept.setVersion(1);
Integer integer = deptMapper.updateById(dept);
System.out.println(integer);
}
根据 MybatisPlus 的 AutoSqlInjector 可以自定义各种你想要的 sql ,注入到全局中,相当于自定义 Mybatisplus 自动注入的方法。
步骤:
1) 在 Mapper 接口中定义相关的 CRUD 方法
2) 扩展 AutoSqlInjector inject 方法,实现 Mapper 接口中方法要注入的 SQL
3) 在 MP 全局策略中,配置 自定义注入器
public interface DeptMapper extends BaseMapper {
int deleteAll();
}
public class MySqlInjector extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class> mapperClass, Class> modelClass, TableInfo table) {
// super.inject(configuration, builderAssistant, mapperClass, modelClass, table);
System.out.println("开始注册自定义sql");
//将EmployeeMapper中定义的deleteAll, 处理成对应的MappedStatement对象,加入到configuration对象中。
//注入的SQL语句
String sql = "delete from "+table.getTableName();
//注入的方法名 一定要与EmployeeMapper接口中的方法名一致
String method = "deleteAll";
//构造SqlSource对象
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
//构造一个删除的MappedStatement
this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
全局配置文件中:
globalConfiguration中全局策略中配置注册器sqlInjector
自定义注入器的应用之 逻辑删除:如果要用逻辑删除那之前的自定义注册起就需要注释掉,把这个逻辑删除的注入器注册进去
1) com.baomidou.mybatisplus.mapper.LogicSqlInjector
2) logicDeleteValue 逻辑删除全局值
3) logicNotDeleteValue 逻辑未删除全局值
4) 在 POJO 的逻辑删除字段 添加 @TableLogic 注解
5) 会在 mp 自带查询和更新方法的 sql 后面,追加『逻辑删除字段』=『LogicNotDeleteValue
默认值』 删除方法: deleteById()和其他 delete 方法, 底层 SQL 调用的是 update tbl_xxx
set 『逻辑删除字段』=『logicDeleteValue 默认值』
com.baomidou.mybatisplus.mapper.MetaObjectHandler
insertFill(MetaObject metaObject)
updateFill(MetaObject metaObject)
metaobject: 元对象. 是 Mybatis 提供的一个用于更加方便,更加优雅的访问对象的属性,
给对象的属性设置值 的一个对象. 还会用于包装对象. 支持对 Object 、Map、Collection
等对象进行包装
本质上 metaObject 获取对象的属性值或者是给对象的属性设置值,最终是要
通过 Reflector 获取到属性的对应方法的 Invoker, 最终 invoke.
步骤:
1) 注解填充字段 @TableFile(fill = FieldFill.INSERT) 查看 FieldFill
2) 自定义公共字段填充处理器
3) MP 全局注入 自定义公共字段填充处理器
@TableField(fill = FieldFill.INSERT_UPDATE)
private String userName;
public class MyMetaObjectHandler extends MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Object userName = getFieldValByName("userName", metaObject);
if(userName == null) {
System.out.println("MyMetaObjectHandler insertFill() 满足条件");
MetaObjectHandler metaObjectHandler = setFieldValByName("userName", "aaa", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
Object userName = getFieldValByName("userName", metaObject);
if(userName == null) {
System.out.println("MyMetaObjectHandler updateFill() 满足条件");
MetaObjectHandler metaObjectHandler = setFieldValByName("userName", "bbb", metaObject);
}
}
}
配置文件中定义好自定义的填充处理器bean,然后加入到全局策略中
MySQL: 支持主键自增。 IdType.Auto
Oracle: 序列(Sequence)
1) 实体类配置主键 Sequence @KeySequence(value=”序列名”,clazz=xxx.class 主键属性类
型)
2) 全局 MP 主键生成策略为 IdType.INPUT
3) 全局 MP 中配置 Oracle 主键 Sequence
com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
4) 可以将@keySequence 定义在父类中,可实现多个子类对应的多个表公用一个 Sequence
@KeySequence(value = "seq_user",clazz=Integer.class)
public class User extends Model {
// @TableId(type=IdType.INPUT)
private Integer id;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String userName;
@TableLogic
private String deleteFlag;
配置文件配置oracle主键生成策略,然后注册主键序列