MybatisPlus<br />一、简介<br />1、Mybatis介绍<br /> 只对Mybatis进行增强不做改变<br />2、代码及文档地址<br /> [https://mp.baomidou.com/](https://mp.baomidou.com/)<br />3、前置知识<br /> Mybatis<br /> Spring<br />Maven<br />二、集成MP<br />1、创建测试表<br /> <br />2、创建JavaBean<br />3、依赖配置<br /> (1)依赖 <br /><dependency><br /> <groupId>com.baomidou</groupId><br /> <artifactId>mybatis-plus</artifactId><br /> <version>2.3</version><br /> </dependency><br /> 无需加入Mybatis和Mybatis-Spring依赖,MP会自动帮我们维护<br /> (2)全局配置文件<br /> <br />4、测试<br /> 测试是否有DataSource和Connection对象<br />5、集成MP(将Mybatis-Plus集成进来)<br /> Mybatis提供的:org.mybatis.spring.SqlSessionFactoryBean<br />Mybatis-Plus提供的:<br />com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean<br />三、入门HelloWorld<br />1、通用CRUD<br /> 实现:让XxxMapper接口继承BaseMapper接口即可。<br /> BaseMapper<T>:泛型指定的就是的当前Mapper接口所操作的实体类<br /> BaseMapper接口:不需要编写XxxMapper.xml,接口内部提供了一系列的<br />方法。<br /> <br />2、插入操作和引出的所有知识点<br /> 方法1:insert(对象); 插入一条记录<br /> 会判断实体对象的属性是否有设置值,没有的就不会出现在sql<br />语句中。<br /><br />@Tabled:主键注解<br /> 属性:<br /> value:属性值和字段名不一致时,需要设置成表中字段名<br /> type:主键生成策略。有5种<br />  <br /> @TableName:表名注解<br /> 属性:<br /> value:实体类和表名不一致时,需要指定表名<br /> resultMap:xml中 resultMap的id。设置此值时则按指定的<br />resultMap封装数据<br /> <br /> @TableField:非主键的字段注解<br /> 该注解在2.3版本之后,很少使用了。因为dbColumnUnderline默认是<br />true。<br />属性:<br /> value:指定表中的字段名与该属性对应<br /> exist:标识该属性是否为表中的字段,默认为true<br /> 作用:当实体类有其它属性时,但该属性不参与任何的CRUD操<br />作,该属性必须设置为@TableField(exist=false)<br /> <br /> (1)插入数据获取主键值<br /> 直接使用对象的getId()方法,就可以获取当前对象的主键值。不<br />需要进行任何的配置。<br /> <br />方法2:insertAllColumn(对象); 插入一条记录<br /> 不管属性有没有设置值,都会出现在sql语句中,没有值的设置尾<br />NULL。<br /> <br />3、全局策略配置<br /> 类:GlobalConfiguration<br /><br />注入到SqlSessionFactoryBean中:<br /> property的name属性:globalConfig<br /> property的ref属性:对应bean的id<br /><br />属性:dbColumnUnderline:驼峰命名来匹配下划线格式。在2.3版本以后,<br />默认为true,不需要配置。<br /> 例如:实体类的lastName属性--->表中的last_name字段名<br />idType:全局的主键策略 <br />tablePrefix:全局的表前缀策略<br /> 配置后,Mybatis-Plus会将前缀与实体类的类名连接起来,然后与数据库中的表名对比。<br />4、更新操作<br /> 方法1:Integer updateById(T); 更新一条记录<br />根据id确定要修改的对象,然后重新修改对象的属性值,再调用方法进行更新数据。只会对非空的属性进行sql语句的更新。<br /> 方法2:updateAllColumnById(T);更新一条记录<br /> 对所有的属性进行sql语句的更新,没有设置值的属性,默认更新为Null<br />5、查询操作<br /> 方法1:T selectById(Serializable id);<br /> 直接传入主键id,就会返回查询结果对象<br /> 方法2:T selectOne(T);<br /> 参数对象可以设置1个或多个属性值,根据参数对象来查找唯一的对象<br /> 查找到多个对象时,会报错。<br /> 方法3:List<T> selectBatchIds(List idList);<br /> 传入一个带有主键id的List来查询数据库,返回List集合对象<br /> 方法4:List<T> selectByMap(Map<String,Object> columnMap);<br /> 参数:String是数据表的字段名 ,Object就是要查的字段值<br /> 返回值:返回的是集合对象<br /> 方法5:T selectPage(RowBounds rowBounds,Wrapper<T> wrapper);<br /> 作用:根据entity条件,查询全部记录(并翻页)<br /> 参数:<br /> RowBounds:分页查询条件(可以为RowBounds.DEFAULT)<br /> 可以传入Page类(实现分页辅助类)<br /> new Page<>(第几页,每页的条数);<br />Wrapper:条件构造器,实体对象封装操作类(可以为null)<br /> 详解:sql语句没有使用limlit关键字,因此该方法用的是RowBounds<br />底层的内存分页(逻辑分页)。后期我们要借助分页插件,实现物<br />理分页(带有limlit关键字)。<br />6、删除操作<br /> 方法1:Integer deleteById(Serializable id);根据主键删除记录<br /> 方法2:Integer deleteByMap(Map<String,Object> columnMap);<br /> 参数:String是数据表的字段名 ,Object就是要查的字段值<br /> 作用:根据多个字段的值,来删除记录<br /> 返回值:返回删除的记录条数<br /> 方法3:Integer deleteBatchIds(List idList);<br /> 参数:多个主键id封装而成的List集合<br /> 作用:根据多个主键来来删除多条记录<br />返回值:删除的记录条数<br />7、MP启动注入SQL原理分析<br /> (1)问题:XxxMapper继承了BaseMapper,BaseMapper提供了通用的CRUD<br />方法,有方法就必须有SQL,因为Mybatis最终还是需要通过<br />SQL语句操作数据。<br /> (2)前置知识:Mybatis源码中比较重要的一些对象,Mybatis框架的执行<br />流程:<br /> Configuration<br /> MappedStatement<br /> ......<br /> (3)通过现象看到本质的东西:<br /> A、XxxMapper的本质是:MapperProxy(代理对象)<br /> B、MapperProxy中的sqlSession,再sqlSessionFactory<br /> <br /> C、sqlSessionFactory中的configuration(全局配置文件)<br /> D、configuration中的MappedStatements<br /> 每一个mappedStatement都表示Mapper接口中的一个方法与<br />Mapper映射文件的SQL。<br /> E、MP在启动就会挨个分析xxMapper中的方法,并且将对应的SQL<br />语句处理好,保存到configuration对象中的mappedStatement<br />中<br /> F、本质:<br /><br /> SqlMethod:枚举对象,内含不完整的模版SQL语句<br /> TableInfo:数据库表的反射对象,可以获取到数据库表相关信息<br /> SqlSource:SQL语句处理对象<br /> MapperBuilderAssistant:用于缓存、SQL参数、查询结果集处理,<br />可以将MappedStatement添加到<br />Configuration中去。<br /> <br />8、通用CRUD小结<br /> (1)以上的所有操作,只需要继承BaseMapper接口就可以使用。<br /> (2)提出需求:分页查询tbl_employee表,年龄在18-50且为男性的,姓<br />名为xx所有用户,这时我们就要使用MP中的条件构造器:<br />EntityWrapper<br /> <br />四、条件构造器EntityWrapper<br />1、简介<br />(1)MP可以通过EntityWrapper或者Condition来让用户自由构建条件,提高<br />效率。<br /> <br />(2)实体包装器,主要用于处理sql拼接,排序,实体参数查询等<br />(3)注意:使用的是数据库表中字段名,不是实体类的属性名<br />(4)条件参数说明:<br /> <br /> <br /> <br />2、selectPage方法<br />需求:分页查询tbl_employee表,年龄在18-50之间性别为男且姓名为Pzm<br />的所有用户。<br /> 注意:每个条件之间默认使用and连接起来的<br /> 实现:<br /> <br /> <br />3、带条件的查询<br /> 需求:查询tbl_employeeb表,性别为女且名字带有“老师”或者邮箱中带<br />有“a”<br /> 方法:List<T> selectList(Wrapper<T> wrapper);<br /> 实现:<br /> <br />4、带条件的修改<br /> 需求:修改名字为Pzm且年龄为21的 <br />方法:Integer update(T entity,Wrapper<T> wrapper);<br />参数:entity:封装修改后的对象<br /> Wrapper:封装条件<br />实现:<br /> <br />5、带条件的删除<br /> 需求:删除名字为LDM且年龄为25的数据<br />方法:Integer delete(Wrapper<T> wrapper);<br />实现:<br /> <br />6、EntityWrapper的常用方法<br />(1)orderBy(“”):默认升序<br /> orderAsc(Collection<String> columns): 升序<br /> orderDesc(Collection<String> columns):降序<br /> last(“”):手动把sql拼接到最后(有sql注入的风险,请谨慎使用)<br />需求:查询性别为女(0),根据age进行排序,简单分页<br /> 实现:<br />  <br />7、使用Condition类<br />除了创建实例对象与EntityWrapper不一样,其余的条件构造方法都是一样的,因为都是来自于Wrapper类的。<br />创建实例:Condition.create();<br /> <br /> <br />五、ActiveRecord(活动记录)<br />1、概述<br /> 一个模型类对应关系型数据库中的一个表,模型类的一个实例对应表中的<br />一行记录。<br />2、使用AR模式<br /> 实现:实体类继承Model类且实现主键指定方法<br /> 实现的方法:返回当前实体类的主键 <br /> <br /> <br />3、AR基本CRUD<br />(1)插入操作<br /> 方法:boolean insert();<br /> 返回值:成功返回true,失败返回false<br /> 实现:<br /> <br />(2)修改操作<br /> 方法:boolean updateById()<br /> 返回值:成功返回true,失败返回false<br /> 实现:<br /> <br />(3)查询操作<br /> 方法1:T selectById()<br /> 返回值:返回查询的结果对象<br /> 实现:<br /> <br /> <br /> 方法2:T selectById(Serializable id)<br /> 返回值:返回查询的结果对象<br /> 实现:<br /> <br /> 方法3:List<T> selectAll()<br /> 返回值:返回表中所有的数据<br /> 实现:<br /> <br /> 方法4:List<T> selectList(Wrapper wrapper)<br /> 返回值:返回查询的结果对象<br /> 实现:<br /> <br /> 方法5:int selectCount(Wrapper wrapper)<br /> 作用:统计查询<br /> 返回值:返回统计的结果值<br /> 实现:<br /> <br /> <br />(4)删除操作(删除不存在的ID逻辑上属于成功)<br /> 方法1:boolean deleteById()<br /> 返回值:删除成功返回true,删除失败返回false。<br /> 实现:<br /> <br /> 方法2:boolean deleteById(Serializable id)<br /> 返回值:删除成功返回true,删除失败返回false<br /> 实现:<br /> <br /> 方法3:boolean delete(Wrapper wrapper)<br /> 返回值:删除成功返回true,删除失败返回false<br /> 实现:<br /> <br />(5)复杂分页操作<br /> 方法:Page<T> selectPage(Page<T> page,Wrapper<T> wrapper)<br /> 实现:<br /> <br />4、AR小结<br />(1)AR模式提供了一种更加简便的方式实现CRUD操作,其本质还是调用的<br />Mybatis对应的方法。<br />(2)到此,我们简单领略了MP的魅力与高效率,MP提供了强大的代码生成器,<br />可以快速生成各类代码,真正的做到了即开即用。<br /> <br />六、代码生成器<br />1、MP的代码生成器和Mybatis的代码生成器:<br /> MP的代码生成器都是基于java代码来生成的。Mybatis基于xml文件<br /> Mybatis的代码生成器可生成:实体类,Mapper接口,Mapper映射文件<br /> MP的代码生成器可生成:实体类(是否支持AR),Mapper接口,Mapper映<br />射文件,Service层,Controller层<br />2、表及字段名策略选择<br /> 在MP中,建议数据库表名和表字段名采用驼峰命名方式,如果采用下划线<br />命名方式,请开启全局下划线开关(默认开启),如果表名字段名命名方法<br />不一致请注解指定,建议保持一致。<br /> <br />3、代码生成器依赖<br /> (1)模版引擎<br /> MP的代码生成器默认使用的是Apache的Velocity模版,也可以更<br />换别的模版引擎<br /><dependency><br /> <groupId>org.apache.velocity</groupId><br /> <artifactId>velocity-engine-core</artifactId><br /> <version>2.0</version><br /></dependency><br /> (2)加入slf4j,查看日志输出<br /><dependency><br /> <groupId>org.slf4j</groupId><br /> <artifactId>slf4j-api</artifactId><br /> <version>1.7.7</version><br /></dependency><br /><dependency><br /> <groupId>org.slf4j</groupId><br /> <artifactId>slf4j-log4j12</artifactId><br /> <version>1.7.7</version><br /></dependency><br /> <br />4、全局配置<br /> 类:GlobalConfig<br /> 方法:<br /> 1、GlobalConfig setActiveRecord(boolean); 是否支持AR模式<br /> 2、GlobalConfig setAuthor(String); 设置作者<br /> 3、GlobalConfig setOutputDir(String); 设置生成路径<br /> 4、GlobalConfig setFileOverride(boolean); 文件是否覆盖<br /> 5、GlobalConfig setIdType(IdType); 主键策略<br /> 6、GlobalConfig setServiceName(String); 设置生成的Service接<br />口的名字的首字母是否<br />为I<br /> 7、GlobalConfig setResultMap(boolean); 是否生成映射文件<br /> 8、GlobalConfig setBaseColumnList(boolean); 是否生成sql片段<br /> <br />5、数据源配置<br /> 类:DataSourceConfig<br /> 方法:<br /> 1、DataSourceConfig setDbType(DbType); 设置数据库的类型<br /> 2、DataSourceConfig setDriverName(String);<br /> 3、DataSourceConfig setUrl(String);<br /> 4、DataSourceConfig setUser(String);<br /> 5、DataSourceConfig setPassword(String);<br /> <br />6、策略配置<br /> 类:StrategyConfig<br /> 方法:<br /> 1、StrategyConfig setDbColumnUnderline(boolean);下划线命名<br /> 2、StrategyConfig setCapitalMode(boolean); 全局大写命名<br /> 3、StrategyConfig setNaming(NamingStrategy.underline_to_camel<br />); (下划线—驼峰)匹配<br /> 4、StrategyConfig setTablePrefix(String); 指定表名前缀<br /> 5、StrategyConfig setInclude(String …); 设置生成的表<br /> <br />7、包名策略配置<br /> 类:PackageConfig<br /> 方法:<br /> 1、PackageConfig setParent(String); 设置父包<br /> 2、PackageConfig setMapper(String); 设置Mapper所在的包<br /> 3、PackageConfig setController(String); 设置Controller的包<br /> 4、PackageConfig setEntity(String);设置实体类所在的包<br /> 5、PackageConfig setXml(String); 设置映射文件所在的包<br /> 6、PackageConfig setServiceImpl();设置Service实现类所在的包<br /> 7、PackageConfig setService();设置Service接口所在的包<br /> <br />8、整合配置<br /> 类:AutoGenerator<br /> 方法:<br /> 1、AutoGenerator setGlobalConfig(GlobalConfig);<br /> 2、AutoGenerator setDataSource(DataSourceConfig);<br /> 3、AutoGenerator setStrategy(StrategyConfig);<br /> 4、AutoGenerator setPackageInfo(PackageConfig);<br /> 5、AutoGenerator execute(); 执行<br /> <br />9、生成代码的解析<br /> EmployeeServiceImpl:<br />1、在ServiceImpl中已经完成了Mapper的注入,可以直接在<br />EmployeeServiceImpl中进行使用<br />2、在ServiceImpl中也帮我们提供了常用的CRUD方法,基本的一些CRUD<br />方法在Service中不需要我们定义<br /> <br /> <br />七、插件扩展<br />1、Mybatis插件机制简介<br />(1)插件机制:<br /> Mybatis通过插件(Interceptor)可以做到拦截四大对象相关方法的执<br />行,根据需求,完成相关数据的动态改变。<br /> 四大对象:<br /> Executor 执行器对象<br /> StatementHandler sql语句编译器对象<br /> ParameterHandler 参数处理器对象<br /> ResultSetHandler 结果集处理器对象<br />(2)插件原理<br /> 四大对象的每个对象在创建时,都会执行interceptorChain.pluginAll<br />(),会经过每个插件对象的plugin()方法,目的是为当前的四大对象创<br />建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行<br />四大对象的方法需要经过代理。<br />(3)配置:<br /> 都是配置在sqlSessionFacotryBean的plugins属性中。(数组)<br /> <br />2、分页插件<br />PaginationInterceptor<br /> 配置:<br /> 1、可以在mybatis-config.xml中配置<br /> 2、在applicationContext.xml中配置:<br /> <br /> 测试:<br /> <br /> Sql语句: SELECT id,last_name AS lastName,email,gender,age<br />FROM tbl_employee LIMIT 0,3<br /> <br />3、注册分页插件后Page对象的使用<br /> 总条数:getTotal();<br /> 当前页:getCurrent();<br />总页数:getPages();<br />每页显示的条数:getSize();<br />是否有上一页:hasPrevious();<br />是否有下一页:hasNext();<br />封装数据:setRecords(List<T> records);<br /> <br />4、执行分析插件<br /> (1)概述:<br />类:SqlExplainInterceptor<br /> 要求:Sql执行分析拦截器,支持Mysql 5.6.3以上版本<br /> 作用:分析DELETE,UPDATE语句,防止小白或者恶意进行DELETE<br />UPDATE全表操作。<br /> 只建议在开发环境中使用,不建议在生产环境使用<br /> (2)原理:在插件的底层,通过SQL语句分析命令:Explain分析当前的SQL<br />语句,根据结果集中的Extra列来断定当前斯否全表操作。<br /> (3)注册插件(配置):<br /> <br /> (4)测试:<br /> <br /> <br /> <br />5、性能分析插件<br />(1)概述:<br />类:PerformanceInterceptor<br /> 作用:用于输出每条SQL语句及其执行时间<br /> 场合:开发环境使用,超过指定时间,停止运行,有助于发现问题<br />(2)注册插件(配置):<br /> <br /> (3)测试:<br /> 超出时间,sql语句还是能执行成功。<br /> <br />6、乐观锁插件<br />(1)概述:<br /> 类:OptimisticLockerInterceptor<br /> 要求:当要更新一条数据时,希望这条记录没有被别人更新<br />原理:<br />取出记录时,获取当前version<br /> 更新时,带上这个version<br /> 执行更新时,set version=yourVersion+1 where version=<br />yourVersion<br /> 如果version不对,就更新失败<br /> @Version:用于注解实体字段,必须要有<br /> (2)注册插件:<br /> <br /> (3)测试:<br /> <br /> <br />八、自定义全局操作<br />1、概述<br />根据MybatisPlus的AutoSqlInjector可以自定义各种你想要的sql,注入到全局中,就相当于时MybatisPlus自带的方法。<br />不需要在xml中写上相应的SQL语句,而是通过扩展AutoSqlInjector在加载Mybatis环境时就注入。<br /> <br />2、AutoSqlInjector<br />步骤:<br />(1)、在Mapper接口中定义相关的CRUD方法<br /> int deleteAll();<br />(2)、扩展AutoInjector的inject方法,实现Mapper接口中方法要注<br />入的SQL<br /><br /> (3)、在MP全局策略中,配置自定义注入器<br /> <br /> <br />3、自定义注入器的应用之逻辑删除<br /> 假删除、逻辑删除:并不会真正的从数据库中将数据删除掉,而是将当前被<br />删除的这条数据中的逻辑删除字段置为删除字段。<br /> (1)概述:<br />1、类:LogicSqlInjetor<br /> 2、logicDeleteValue:逻辑删除全局值<br /> 3、logicNotDeleteValue:逻辑未删除全局值<br /> 4、逻辑删除字段添加@TableLogic注解<br /> 5、会在mp自带查询和更新方法的sql后面,追加【逻辑删除字段】<br />=【LogicNotDeleteValue(默认值)】 删除方法:deleteById和<br />其它delete方法,底层SQL调用的是update tbl_xxx set<br />【逻辑删除字段】=【logicDeleteValue】<br />(2)配置注入器:<br /> <br />(3)创建数据表<br /> 1:代表未删除 -1:代表已删除 <br />(4)创建实体类和Mapper接口(略)<br /> <br />(5)测试:<br /> <br /> <br /> <br /> <br /> <br />九、公共字段自动填充<br />1、概述:在更新或插入时,对没有的提供的数据,进行默认数据的填充。<br />2、元数据处理器接口<br /> 类:MetaObjectHandler<br /> 方法:<br /> 1、insertFill(MetaObject metaObject); 插入元对象字段填充<br /> 2、updateFill(MetaObject metaObject); 更新元对象字段填充<br /> 对象:<br /> MetaObject:是Mybatis用于更方便的访问对象的属性,给对象的属<br />性设置值的一个对象,还用于包装对象,支持Object、<br />Map、Collection等对象进行包装。<br /> 本质:获取对象的属性值或者给对象的属性设置值,最终是要通过<br />Reflector获取到属性的对应方法的invoker,最终invoker。<br />3、开发步骤<br />(1)注解填充自动 @TableField(fill=FieldFill.INSERT)<br /> 属性:fill<br /> 值:<br /> <br />(2)自定义公共字段填充处理器<br /> 1、自定义类,继承MetaObjectHandler,实现方法<br /> 2、获取到需要被填充的字段的值<br /> getFieldValueByName(fieldname,metaObject);<br /> 3、判断字段是否为空<br /> 4、对字段进行填充<br /> SetFieldValueByName(fieldname,值,metaObject);<br />(3)MP全局注入自定义公共字段填充处理器<br /> 配置到全局配置类中。<br /> <br /> <br />十、Oracle主键Sequence<br />Mysql:支持主键自增 IdType.AUTO<br />Oracle:序列(Sequence)<br />1、Oracle驱动依赖的问题<br /> 因为Oracle授权问题,不能从Maven仓库中下载Oracle驱动<br />2、Oracle的相关知识<br /> 创建序列:create sequence seq_user start with 100 increment by 2;<br /> 查询序列的下一个值:select seq_user.nextval from dual;<br /> 查询序列的当前值:select seq_user.currval from dual;<br />3、步骤:<br /> (1)实体类配置主键Sequence,@KeySequence(value=”序列<br />名”,clazz=xx.class 主键属性类型)<br /><br />(2)全局MP主键生成策略:IdType.INPUT<br /> <br />(3)全局MP配置Oracle主键Sequence<br /> <br /> (4)可以将@KeySequence定义在父类中,可实现多个子类对应的多个表公<br />用一个Sequence<br /> <br /> <br />十一、Idea快速开发插件<br />1、功能<br /> 根据接口中的方法自动生成xml结构<br />