关于mybatis-plus:聊聊mybatisplus的sql加载顺序

序本文次要钻研一下如果mybatis mapper定义了多个同名办法会不会有问题 MybatisConfigurationcom/baomidou/mybatisplus/core/MybatisConfiguration.java /** * MybatisPlus 加载 SQL 程序: * <p> 1、加载 XML中的 SQL </p> * <p> 2、加载 SqlProvider 中的 SQL </p> * <p> 3、XmlSql 与 SqlProvider不能蕴含雷同的 SQL </p> * <p>调整后的 SQL优先级:XmlSql > sqlProvider > CurdSql </p> */ @Override public void addMappedStatement(MappedStatement ms) { if (mappedStatements.containsKey(ms.getId())) { /* * 阐明已加载了xml中的节点; 疏忽mapper中的 SqlProvider 数据 */ logger.error("mapper[" + ms.getId() + "] is ignored, because it exists, maybe from xml file"); return; } mappedStatements.put(ms.getId(), ms); }MybatisSqlSessionFactoryBeancom/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java ...

August 27, 2023 · 7 min · jiezi

关于mybatis-plus:聊聊mybatisplus的SafetyEncryptProcessor

序本文次要钻研一下mybatis-plus的SafetyEncryptProcessor SafetyEncryptProcessormybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/SafetyEncryptProcessor.java public class SafetyEncryptProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { /** * 命令行中获取密钥 */ String mpwKey = null; for (PropertySource<?> ps : environment.getPropertySources()) { if (ps instanceof SimpleCommandLinePropertySource) { SimpleCommandLinePropertySource source = (SimpleCommandLinePropertySource) ps; mpwKey = source.getProperty("mpw.key"); break; } } /** * 解决加密内容 */ if (StringUtils.isNotBlank(mpwKey)) { HashMap<String, Object> map = new HashMap<>(); for (PropertySource<?> ps : environment.getPropertySources()) { if (ps instanceof OriginTrackedMapPropertySource) { OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps; for (String name : source.getPropertyNames()) { Object value = source.getProperty(name); if (value instanceof String) { String str = (String) value; if (str.startsWith("mpw:")) { map.put(name, AES.decrypt(str.substring(4), mpwKey)); } } } } } // 将解密的数据放入环境变量,并处于第一优先级上 if (CollectionUtils.isNotEmpty(map)) { environment.getPropertySources().addFirst(new MapPropertySource("custom-encrypt", map)); } } }}SafetyEncryptProcessor实现了EnvironmentPostProcessor接口,在postProcessEnvironment办法中先是找到mpw.key,而后遍历所有PropertySource的所有属性,找到mpw:结尾的,而后进行解密并替换到密文,最初放在environment的第一个PropertySourcespring.factoriesmybatis-plus-boot-starter/src/main/resources/META-INF/spring.factories ...

August 26, 2023 · 1 min · jiezi

关于mybatis-plus:Jimmer-VS-MyBatisPlus查询自关联表

首发于Enaium的集体博客 本文是对Jimmer文档中对象抓取器-自关联递归抓取局部的介绍,之后会比照MyBatisPlus的查问自关联表的能力。 对象抓取器是 jimmer-sql 一个十分弱小的特色,具备可媲美 GraphQL 的能力。即便用户不采纳任何 GraphQL 相干的技术栈,也能在 SQL 查问层面失去和 GraphQL 类似的对象图查问能力。筹备数据库和实体类create table tree_node( node_id bigint not null, name varchar(20) not null, parent_id bigint);alter table tree_node add constraint pk_tree_node primary key(node_id);alter table tree_node add constraint uq_tree_node unique(parent_id, name);alter table tree_node add constraint fk_tree_node__parent foreign key(parent_id) references tree_node(node_id);insert into tree_node( node_id, name, parent_id) values (1, 'Home', null), (2, 'Food', 1), (3, 'Drinks', 2), (4, 'Coca Cola', 3), (5, 'Fanta', 3), (6, 'Bread', 2), (7, 'Baguette', 6), (8, 'Ciabatta', 6), (9, 'Clothing', 1), (10, 'Woman', 9), (11, 'Casual wear', 10), (12, 'Dress', 11), (13, 'Miniskirt', 11), (14, 'Jeans', 11), (15, 'Formal wear', 10), (16, 'Suit', 15), (17, 'Shirt', 15), (18, 'Man', 9), (19, 'Casual wear', 18), (20, 'Jacket', 19), (21, 'Jeans', 19), (22, 'Formal wear', 18), (23, 'Suit', 22), (24, 'Shirt', 22);@Entitypublic interface TreeNode { @Id @Column(name = "NODE_ID") long id(); String name(); @Null @ManyToOne TreeNode parent(); @OneToMany(mappedBy = "parent") List<TreeNode> childNodes();}指定查问的深度咱们能够看到,这是一个自关联的表,每个节点都有一个父节点,也能够有多个子节点。 ...

May 30, 2023 · 6 min · jiezi

关于mybatis-plus:dbtemplate-是什么

dbtemplate是什么即不是mybatis,又不是orm,那dbtemplate到底实现了什么性能? 通过配置文件,实现操作数据表的(增|删|改|查)能力。 通过配置文件,可配置服务端口,并启动服务(反对协定: HTTP 和 GRPC ) 可嵌入到设施上,充当拜访设施端数据库的中间件,也能够是小型WEB服务端的抉择(当然要看你业务的复杂程度,基本上数据表的操作都能满足,适宜疾速交付使用)。 前端通过HTTP协定(或GRPC协定),POST一个公开的API接口并传递相应参数,就能够操作数据表。 传递的参数会不会受到SQL注入?配置文件反对配置SQL注入正则表达式,开发人员当时要设计好SQL语句模板哟。 集成场景是HTTP API集成 或 GRPC集成 调用 集成到嵌入式设施,用于设施根本信息配置应用.疾速搭建小型服务端,实用于疾速交付产品场景.如何应用- 服务端运行dbtemplate -fileUrl dbtemplate.xml - 前端调用通过一个API 实现 增|删|改|查 操作 postman调试阐明: Method: POSTURL: http://<ip>:<port>/postCommonMethodHeader: KEY为 Content-Type VALUE为 application/x-www-form-urlencodedBody: KEY为 jsondata VALUE为 { "id":"1", "method":"sel", "cols":"*", "where":" and d_ip like '%192.168.' ", "pageSize":10, "currentPage":0 }参考资料https://github.com/hw2499/dbtemplate

April 22, 2023 · 1 min · jiezi

关于mybatis-plus:MybatisPlus详解一篇带入了解底层原理

一. MP简介 咱们晓得,Mybatis属于一个半自动的ORM框架。之所以说Mybatis是一个半自动的ORM框架,起因是它还须要咱们本人在注解或是映射文件中编写SQL语句,并没有实现齐全的自动化。SQL语句的编写,尽管减少了我的项目和业务需要实现的灵活性,但对一些根本表的操作而言,无疑减少了数据库操作的复杂度,显得没有那么不便。 而Mybatis-Plus则是全自动的ORM框架,依照开闭准则,在不影响Mybatis现有性能的状况下,实现了对Mybatis的性能加强。如果你之前有过Mybatis的应用教训,当初学习Mybatis-Plus几乎就是手到擒来。 明天就带大家来学习一下Mybatis-Plus框架的根本应用,请掏出小本本吧。 二. Mybatis-Plus特点MP具备如下根本特点:通过在实体类中与数据库表进行映射;无需编写SQL语句,简化了CRUD操作;通常实用于单表。 三. MP应用 接下来会在SpringBoot我的项目环境中,带着大家一起应用Mybatis-Plus。 1、新建SpringBoot我的项目创立SpringBoot我的项目的过程,在这里就给大家省略了,如果有不相熟的同学,能够参考之前对于SpringBoot的教程文章 2、增加外围依赖咱们在SpringBoot我的项目中增加须要用到的外围依赖包。 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!-- MySql --><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version></dependency><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1.tmp</version></dependency><!-- 连接池 --><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version></dependency><!--简化bean代码的工具包--><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.4</version></dependency><dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version></dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version></dependency></dependencies>  所以,实体类中就能够省去CRUD办法的代码实现。package com.qf.pro.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.qf.pro.pojo.User; public interface UserDao extends BaseMapper<User> { //BaseMapper<User> 默认封装了CRUD办法,通过泛型制订了所操作的实体类及表} 编写配置类这样当SpringBoot启动时,就能够扫描到dao层代码所在的包。package com.qf.mp2103.dao;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; @Configuration@MapperScan("com.qf.mp2103.dao")public class MybatisPlusConfig { @Beanpublic PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor();}} 业务实现咱们要在业务逻辑层里调用各种CRUD办法,这也是Mybatis-Plus比拟外围、重要的点,MybatisPlus会依据之前的配置主动生成SQL语句。package com.qf.mp2103.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.qf.mp2103.dao.UsersDao;import com.qf.mp2103.pojo.Users;import com.qf.mp2103.service.UsersService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; ...

April 10, 2023 · 2 min · jiezi

关于mybatis-plus:底层到底做了什么-mybatisplus的一次select调用过程

应用mybatis-plus创立db mapper,只须要写一个接口继承BaseMapper,比方示例中的EntityMapper。 @Mapper@Repositorypublic interface EntityMapper extends BaseMapper<Entity> {} 本文将解释在底层一次select调用是怎么实现。 次要包含以下几个局部: 外围类及包容器初始化Mapper bean初始化代理办法调用外围类及所在包次要波及以下包和类。 <artifactId>mybatis-plus-annotation</artifactId> MybatisSqlSessionFactoryBean ServiceImpl<artifactId>mybatis-spring</artifactId> MapperFactoryBean<artifactId>mybatis-plus-core</artifactId> MybatisConfiguration MybatisMapperRegistry MybatisMapperProxyFactory MybatisMapperProxy MybatisMapperMethod容器初始化spring 递归初始化以下类,包含: MybatisPlusAutoConfigurationMybatisSqlSessionFactoryBeanMybatisConfigurationMybatisMapperRegistry这里不一一阐明各类的初始化过程,只拿出MybatisMapperRegistry。该类用来理论存储mapper的实现 public class MybatisMapperRegistry extends MapperRegistry { private final Configuration config; private final Map<Class<?>, MybatisMapperProxyFactory<?>> knownMappers = new HashMap();}mapper bean的初始化1、spring调用 MapperFactoryBean 初始化申明的mapper接口的bean。 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { public T getObject() throws Exception { return this.getSqlSession().getMapper(this.mapperInterface); }}该办法会递归调用上文曾经初始化的 MybatisConfiguration、 MybatisMapperRegistry,最终应用 MybatisMapperProxyFactory 生成代理类。 生成代理类,并放入 MybatisMapperRegistry 容器中public class MybatisMapperProxyFactory<T> {protected T newInstance(MybatisMapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }}select调用获取注入的代理类bean调用select办法理论调用代理办法 ...

February 22, 2023 · 1 min · jiezi

关于mybatis-plus:关于使用MyBatisPlus后id变一长串雪花算法的踩坑

我建的表是这样的: create table user( id bigint auto_increment comment 'id' primary key, username varchar(256) null comment '用户昵称', userAccount varchar(256) null comment '账号', avatarUrl varchar(1024) null comment '用户头像', gender tinyint null comment '性别', userPassword varchar(512) not null comment '明码', phone varchar(128) null comment '电话', email varchar(512) null comment '邮箱', userStatus int default 0 not null comment '用户转态 0 失常', createTime datetime default CURRENT_TIMESTAMP null comment '创立工夫', updateTime datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新工夫', isDelete tinyint default 0 null invisible comment '是否逻辑删除 默认0') comment '用户';能够看到我的id是bigint 自增,但自测的时候: ...

January 12, 2023 · 1 min · jiezi

关于mybatis-plus:MyBatisPlus之雪花算法

背景须要抉择适合的计划去应答数据规模的增长,以应答逐步增长的拜访压力和数据量。数据库的扩大形式次要包含:业务分库、主从复制,数据库分表。 数据库分表将不同业务数据扩散存储到不同的数据库服务器,可能撑持百万甚至千万用户规模的业务,但如果业务持续倒退,同一业务的单表数据也会达到单台数据库服务器的解决瓶颈。例如,淘宝的几亿用户数据,如果全副寄存在一台数据库服务器的一张表中,必定是无奈满足性能要求的,此时就须要对单表数据进行拆分。单表数据拆分有两种形式:垂直分表和程度分表。示意图如下: 垂直分表垂直分表适宜将表中某些不罕用且占了大量空间的列拆分进来。例如,后面示意图中的 nickname 和 description 字段,假如咱们是一个婚恋网站,用户在筛选其余用户的时候,次要是用 age 和 sex 两个字段进行查问,而 nickname 和 description 两个字段次要用于展现,个别不会在业务查问中用到。description 自身又比拟长,因而咱们能够将这两个字段独立到另外一张表中,这样在查问 age 和 sex 时,就能带来肯定的性能晋升。 程度分表程度分表适宜表行数特地大的表,有的公司要求单表行数超过 5000 万就必须进行分表,这个数字能够作为参考,但并不是相对规范,要害还是要看表的拜访性能。对于一些比较复杂的表,可能超过 1000万就要分表了;而对于一些简略的表,即便存储数据超过 1 亿行,也能够不分表。但不管怎样,当看到表的数据量达到千万级别时,作为架构师就要警惕起来,因为这很可能是架构的性能瓶颈或者隐患。程度分表相比垂直分表,会引入更多的复杂性,例如要求全局惟一的数据id该如何解决。 主键自增①以最常见的用户 ID 为例,能够依照 1000000 的范畴大小进行分段,1 ~ 999999 放到表 1中,1000000 ~ 1999999 放到表2中,以此类推。 ②简单点:分段大小的选取。分段太小会导致切分后子表数量过多,减少保护复杂度;分段太大可能会导致单表仍然存在性能问题,个别倡议分段大小在 100 万至 2000 万之间,具体须要依据业务选取适合的分段大小。 ③长处:能够随着数据的减少平滑地裁减新的表。例如,当初的用户是 100 万,如果减少到 1000 万,只须要减少新的表就能够了,原有的数据不须要动。 ④毛病:散布不平均。如果依照 1000 万来进行分表,有可能某个分段理论存储的数据量只有 1 条,而另外一个分段理论存储的数据量有 1000 万条。 取模①同样以用户 ID 为例,如果咱们一开始就布局了 10 个数据库表,能够简略地用 user_id % 10 的值来示意数据所属的数据库表编号,ID 为 985 的用户放到编号为 5 的子表中,ID 为 10086 的用户放到编号为 6 的子表中。 ...

September 15, 2022 · 1 min · jiezi

关于mybatis-plus:MyBatusPlus保姆级快速上手教程

为简化开发而生Mybatis简化JDBC操作 MyBatis-Plus(简称 MP)是一个 MyBatis 的加强工具,在 MyBatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。 1、个性无侵入:只做加强不做扭转,引入它不会对现有工程产生影响,如丝般顺滑损耗小:启动即会主动注入根本 CURD,性能根本无损耗,间接面向对象操作弱小的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过大量配置即可实现单表大部分 CRUD 操作,更有弱小的条件结构器,满足各类应用需要反对 Lambda 模式调用:通过 Lambda 表达式,不便的编写各类查问条件,无需再放心字段写错反对主键主动生成:反对多达 4 种主键策略(内含分布式惟一 ID 生成器 - Sequence),可自在配置,完满解决主键问题反对 ActiveRecord 模式:反对 ActiveRecord 模式调用,实体类只需继承 Model 类即可进行弱小的 CRUD 操作反对自定义全局通用操作:反对全局通用办法注入( Write once, use anywhere )内置代码生成器:采纳代码或者 Maven 插件可疾速生成 Mapper 、 Model 、 Service 、 Controller 层代码,反对模板引擎,更有超多自定义配置等您来应用内置分页插件:基于 MyBatis 物理分页,开发者无需关怀具体操作,配置好插件之后,写分页等同于一般 List 查问分页插件反对多种数据库:反对 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库内置性能剖析插件:可输入 Sql 语句以及其执行工夫,倡议开发测试时启用该性能,能疾速揪出慢查问内置全局拦挡插件:提供全表 delete 、 update 操作智能剖析阻断,也可自定义拦挡规定,预防误操作2、反对数据库mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver达梦数据库 、 虚谷数据库 、 人大金仓数据库3、疾速开始1、创立数据库DROP TABLE IF EXISTS user;CREATE TABLE user( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id));INSERT INTO user (id, name, age, email) VALUES(1, 'Jone', 18, 'test1@baomidou.com'),(2, 'Jack', 20, 'test2@baomidou.com'),(3, 'Tom', 28, 'test3@baomidou.com'),(4, 'Sandy', 21, 'test4@baomidou.com'),(5, 'Billie', 24, 'test5@baomidou.com');2、新建Spring Boot我的项目导入依赖 ...

September 4, 2022 · 4 min · jiezi

关于mybatis-plus:mybatisplus使用selectOne方法查询多条记录报错的解决方案

mybatis-plus在应用selectOne办法查问记录查到多条时会抛出异样,但有些业务场景须要只取一条的状况,查出来数组再取第一个的计划显得也不不便,能够用如下aop的办法解决: @Aspect@Componentpublic class MybatisAspectj { // 配置织入点 @Pointcut("execution(public * com.baomidou.mybatisplus.core.mapper.BaseMapper.selectOne(..))") public void selectOneAspect() { } @Before("selectOneAspect()") public void beforeSelect(JoinPoint point) { Object arg = point.getArgs()[0]; if (arg instanceof AbstractWrapper) { arg = (AbstractWrapper) arg; ((AbstractWrapper) arg).last("limit 1"); } }}首先创立本人的mapper继承BaseMapper(惯例操作),之后创立这个aop配置类,对selectOne办法进行解决。以上内容转载自:https://blog.csdn.net/qq_4371...

August 16, 2022 · 1 min · jiezi

关于mybatis-plus:MybatisX工具快速代码生成

MybatisX插件在idea疾速代码生成1.应用idea的Database工具连贯通数据库略 2.操作2.1 抉择MybatisX-Generator选中所有表->右键抉择->MybatisX-Generator 2.2 抉择选项11.module path抉择我的项目模块2.base package写本人的包名3.ignore table prefix:表名有前缀须要疏忽,填写上4.表名和className的对应关系实时会列出来2.3 抉择选项21.抉择Mybatis-Plus32.去掉toString/hashCode/equals3.勾选Lombok4.抉择Mybatis-plus35.看下目录对不?点击实现即可

June 17, 2022 · 1 min · jiezi

关于mybatis-plus:假装是小白之重学MyBatis二

前言本篇咱们来介绍MyBatis插件的开发,这个也是来源于我之前的一个面试经验,面试官为我如何统计Dao层的慢SQL,我过后的答复是借助于Spring的AOP机制,拦挡Dao层所有的办法,但面试官又问,这事实上不齐全是SQL的执行工夫,这其中还有其余代码的工夫,问我还有其余思路吗? 我想了想说没有,面试官接着问,有接触过MyBatis插件的开发吗? 我说没接触过。 但前面也给我过了,我认为这个问题是有价值的问题,所以也放在了我的学习打算中。 看本篇之前倡议先看: 《代理模式-AOP绪论》《伪装是小白之重学MyBatis(一)》如果有人问下面两篇文章在哪里能够找的到,能够去掘金或者思否翻翻,目前公众号还没有,预计年中会将三个平台的文章对立一下。 概述翻阅官网文档的话,MyBatis并没有给处插件的具体定义,但基本上还是拦截器,MyBatis的插件就是一些可能拦挡某些MyBats外围组件办法,加强性能的拦截器。官网文档中列出了四种可供加强的切入点: Executor执行SQL的外围组件。拦挡Executor 意味着要烦扰或加强底层执行的CRUD操作ParameterHandler拦挡该ParameterHandler,意味着要烦扰SQL参数注入、读取的动作。ResultSetHandler拦挡该ParameterHandler, 要烦扰/加强封装后果集的动作StatementHandler拦挡StatementHandler ,则意味着要烦扰/加强Statement的创立和执行的动作当然还是从HelloWorld开始要做MyBatis的插件,首先要实现MyBatis的Interceptor 接口 , 留神类不要导错了,Interceptor很热门,该类位于org.apache.ibatis.plugin.Interceptor下。实现该接口,MyBatis会将该实现类当作MyBatis的拦截器,那拦挡哪些办法,该怎么指定呢? 通过@Intercepts注解来实现,上面是应用示例: @Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))public class MyBatisPluginDemo implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("into invocation .........."); System.out.println(invocation.getTarget()); System.out.println(invocation.getMethod().getName()); System.out.println(Arrays.toString(invocation.getArgs())); return invocation.proceed(); }}@Intercepts能够填多个@Signature,@Signature是办法签名,type用于定位类,method定位办法名,args用于指定办法的参数类型。三者加在一起就能够定位到具体的办法。留神写完还须要将此插件注册到MyBatis的配置文件中,让MyBatis加载该插件。留神这个标签肯定要放在environments下面,MyBatis严格限制住了标签的程序。 <plugins> <plugin interceptor="org.example.mybatis.MyBatisPluginDemo"></plugin></plugins>咱们来看下执行后果: 性能剖析插件走起那拦挡谁呢? 目前也只有Executor 和StatementHandler 供咱们抉择,咱们自身是要看SQL耗时,Executor 离SQL执行还有些远,一层套一层才走到SQL执行,MyBatis中标签的执行过程在《MyBatis源码学习笔记(一) 初遇篇》曾经讲述过了,这里不再赘述,目前来看StatementHandler 是离SQL最近的, 它的实现类就间接走到JDBC了,所以咱们拦挡StatementHandler ,那有的插入插了很多值,咱们要不要拦挡,当然也要拦挡, 咱们的插件办法如下: @Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}), @Signature(type = StatementHandler.class,method = "update" ,args = Statement.class )})public class MyBatisSlowSqlPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("-----开始进入性能剖析插件中----"); long startTime = System.currentTimeMillis(); Object result = invocation.proceed(); long endTime = System.currentTimeMillis(); // query办法入参是statement,所以咱们能够将其转为Statement if (endTime - startTime > 1000){ } return result; }}那对应的SQL该怎么拿? 咱们还是到StatementHandler去看下: ...

May 2, 2022 · 5 min · jiezi

关于mybatis-plus:Mybatisplus-分页插件多条件查询

mybatis-plus官网提供了分页插件,(spring-boot)应用办法如下: //Spring boot形式@Configuration@MapperScan("com.test.*.mapper*")public class MybatisPlusConfig { // 旧版 @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置申请的页面大于最大页后操作, true调回到首页,false 持续申请 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限度数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对局部 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; } // 最新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); return interceptor; }}如何辨别新旧版呢?其实你把这两种代码都复制到你的我的项目里,哪个类存在就用哪个办法。 注入分页插件后,如何应用呢? mapper写法: // 这是mapper本人提供的办法,参数是wrapper 实用于单表查 <P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);// 自定义sql,实用于多表联查IPage<UserVO> queryUserList(Page<UserVO> page, @Param("dto") ConditionDTO conditionDTO);必须要次要的点:1.Page为IPage的实现类,分页返回和传入Page是同一个对象2.Page类必须放在第一位3.第二个参数和后续参数必须加@Param,(根本类型和实体类型都须要加),否则会报找不到属性谬误。 ...

December 16, 2021 · 1 min · jiezi

关于mybatis-plus:MyBatisPlus-SQLServer-分页查询

SpringBoot 演示我的项目: POM<!-- MyBatis-Plus --><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.4</version></dependency><!-- SQLServer 驱动--><dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>sqljdbc4</artifactId> <version>4.0</version></dependency>Config# DataSource Configspring: datasource: driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver url: jdbc:sqlserver://127.0.0.1:1433;databaseName=my_db username: sa password: 123456# Print SQLmybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImplModel@Data@TableName("user")public class User { private Long id; private String name;}Mapper@Servicepublic interface UserMapper extends BaseMapper<User> {}Test@SpringBootTestpublic class LessonTest { @Autowired private UserMapper userMapper; /** * 测试分页获取用户 */ @Test public void testPageUsers() { // 第 1 页,每页 10 条记录 Page<User> page = new Page<>(1, 10); // 设置查问条件:依照用户名排序 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.orderByAsc("Name"); // 分页获取用户(可在控制台查看生成的 SQL) Page<User> users = userMapper.selectPage(page, wrapper); // 验证用户数应为 10 assert users.size() == 10; }}

December 2, 2021 · 1 min · jiezi

关于mybatis-plus:mybatis批量插入自动生成主键跟日期

在网上查了很多对于mybatis-plus的批量插入,因为大多应用自增主键,不须要主动生成uuid主键网上的大部分代码为<insert id="insertBatch" parameterType="java.util.List"> insert into user (id, name, age, create_date, create_time, create_date_time) values <foreach collection="list" item="item" separator=","> <trim prefix="(" suffix=")" suffixOverrides=","> #{item.id}, #{item.name}, #{item.age}, #{item.createDate}, #{item.createTime},#{item.createDateTime} </trim> </foreach></insert>下面这种形式是必须传入列表时就生成id,但有时候并不想这样做,想间接从前端传入列表就进行批量插入,而user表主键id又不是自增型,此时想到了一个上面这种形式。<insert id="insertBatch" parameterType="java.util.List"> insert into user (id, name, age, create_date) values <foreach collection="list" item="item" separator=","> <trim prefix="(" suffix=")" suffixOverrides=","> (select replace(uuid(), '-', '') as id), #{item.name}, #{item.age}, current_date(),current_time(),current_timestamp() </trim> </foreach></insert>replace(uuid(), '-', '') 将生成的uuid格局中的-替换''成32位的字符串current_date 生成yyyy-MM-dd日期格局current_time 生成HH:mm:ss工夫格局current_timestamp 生成yyyy-MM-dd HH:mm:ss日期工夫格局

September 2, 2021 · 1 min · jiezi

关于mybatis-plus:Mybatisplus分页

增加依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency>在启动类编辑 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); return interceptor; }Mapper层编写IPage<User> getList(Page<Object> page);xml文件编写SQL <select id="getList" resultMap="getUserDate"> select * from user<!-- select * from user 最初不能增加;号--> </select>Test测试 @Test void Test01(){ Page<Object> page = new Page<>(0, 2); List<User> records = userMapper.getList(page).getRecords(); records.forEach(item->System.out.println(item)); }

August 29, 2021 · 1 min · jiezi

关于mybatis-plus:报错-Invalid-bound-statement-not-found-comxxxmapperxxx

Mybaits-puls我的项目启动时报错 Invalid bound statement (not found): com.xxx.mapper.xxx起因:我的项目启动时未找到mapper中的办法 解决办法:在springboot或mybaits-puls的配置文件中加上: mybatis-plus.mapperLocations=classpath:XXX/XXXX/mapper/**/*.xml 地址最终指向你的xml文件即可

August 26, 2021 · 1 min · jiezi

关于mybatis-plus:Mybatis-Plus-自定义sql-多表-带条件-分页-查询

原文链接:Mybatis Plus 自定义sql 多表 带条件 分页 查问

August 16, 2021 · 1 min · jiezi

关于mybatis-plus:学习MyBatisPlus3这一篇就够了

原文链接:学习MyBatis-Plus3这一篇就够了

August 15, 2021 · 1 min · jiezi

关于mybatis-plus:Be-Extra-Careful-about-Pitfalls-of-MyBatisPlus-2x

What an Unreliable Lad You Are @TableFieldMybatis-Plus introduces many powerful annotations for us to indicate the mapping between entity properties and table fields. It's a great coding experience working with those annotations and IService relevant helper class. However, it's actually not true in Mybatis-Plus 2.x. Why? @TableField in 3.x could replace ResultMap fully, even applied in customized Mapper select statement like the below example. package com.john.model;@TableName("user")public class User { @TableId private String id; @TableField("user_name") private String userName;}<mapper> <select id="getUsers" resultType="com.john.model.User"> select * from user </select></mapper>Believe me gentles, 2.x would let you down definitely. @TableField is out of work in above situation. What we have to do is declare the relations by ResultMap, or keep the entity property name as the same as the table field which is case-sensitive. ...

August 13, 2021 · 2 min · jiezi

关于mybatis-plus:mybatis-plus-看这篇就够了一发入魂

mybatis-plus是一款Mybatis加强工具,用于简化开发,提高效率。下文应用缩写mp来简化示意mybatis-plus,本文次要介绍mp搭配SpringBoot的应用。 注:本文应用的mp版本是以后最新的3.4.2,晚期版本的差别请自行查阅文档 官方网站:baomidou.com/ 疾速入门创立一个SpringBoot我的项目导入依赖 <!-- pom.xml --> <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>mybatis-plus</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mybatis-plus</name> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>配置数据库 # application.yml spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/yogurt?serverTimezone=Asia/Shanghai username: root password: root mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印创立一个实体类 package com.example.mp.po; import lombok.Data; import java.time.LocalDateTime; @Data public class User { private Long id; private String name; private Integer age; private String email; private Long managerId; private LocalDateTime createTime; }创立一个mapper接口 package com.example.mp.mappers; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.mp.po.User; public interface UserMapper extends BaseMapper<User> { }在SpringBoot启动类上配置mapper接口的扫描门路 package com.example.mp; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.example.mp.mappers") public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); } }在数据库中创立表 DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键', name VARCHAR(30) DEFAULT NULL COMMENT '姓名', age INT(11) DEFAULT NULL COMMENT '年龄', email VARCHAR(50) DEFAULT NULL COMMENT '邮箱', manager_id BIGINT(20) DEFAULT NULL COMMENT '直属下级id', create_time DATETIME DEFAULT NULL COMMENT '创立工夫', CONSTRAINT manager_fk FOREIGN KEY(manager_id) REFERENCES user (id) ) ENGINE=INNODB CHARSET=UTF8; INSERT INTO user (id, name, age ,email, manager_id, create_time) VALUES (1, '大BOSS', 40, 'boss@baomidou.com', NULL, '2021-03-22 09:48:00'), (2, '李经理', 40, 'boss@baomidou.com', 1, '2021-01-22 09:48:00'), (3, '黄主管', 40, 'boss@baomidou.com', 2, '2021-01-22 09:48:00'), (4, '吴组长', 40, 'boss@baomidou.com', 2, '2021-02-22 09:48:00'), (5, '小菜', 40, 'boss@baomidou.com', 2, '2021-02-22 09:48:00')编写一个SpringBoot测试类 package com.example.mp; import com.example.mp.mappers.UserMapper; import com.example.mp.po.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class SampleTest { @Autowired private UserMapper mapper; @Test public void testSelect() { List<User> list = mapper.selectList(null); assertEquals(5, list.size()); list.forEach(System.out::println); } }筹备工作实现 ...

May 19, 2021 · 14 min · jiezi

关于mybatis-plus:mybatisplus代码生成器完整示例代码

间接代码展现: package cn.qxstar;import cn.qxstar.common.base.entity.BaseEntity;import cn.qxstar.common.utils.web.controller.BaseController;import com.baomidou.mybatisplus.generator.config.rules.DateType;import org.junit.Test;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.generator.AutoGenerator;import com.baomidou.mybatisplus.generator.config.DataSourceConfig;import com.baomidou.mybatisplus.generator.config.GlobalConfig;import com.baomidou.mybatisplus.generator.config.PackageConfig;import com.baomidou.mybatisplus.generator.config.StrategyConfig;import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;public class TestMP { /** * 代码生成 示例代码 */ @Test public void testGenerator() { //1. 全局配置 GlobalConfig config = new GlobalConfig(); config.setOpen(false) .setAuthor("莐星") // 作者 .setOutputDir("D:\\softWare\\IDEA\\workspace\\chstar-blog\\chstar-service\\biz-service\\src\\main\\java") // 生成门路 .setFileOverride(true) // 文件笼罩 .setIdType(IdType.ASSIGN_ID) // 主键策略 数字id .setServiceName("%sService") // 设置生成的service接口的名 .setMapperName("%sMapper") .setServiceImplName("%sServiceImpl") .setControllerName("%sController") .setSwagger2(true) .setBaseResultMap(true) .setBaseColumnList(true) .setXmlName("%sMapper") .setDateType(DateType.TIME_PACK); //2. 数据源配置 DataSourceConfig dsConfig = new DataSourceConfig(); dsConfig.setDbType(DbType.MYSQL) // 设置数据库类型 .setDriverName("com.mysql.cj.jdbc.Driver") .setUrl("jdbc:mysql://localhost:3306/chstar-blog") .setUsername("root") .setPassword("123456"); //3. 策略配置 StrategyConfig stConfig = new StrategyConfig(); stConfig.setCapitalMode(true) //全局大写命名 .setLogicDeleteFieldName("deleted") //NamingStrategy.underline_to_camel下划线转驼峰命名 user_id -> userId .setNaming(NamingStrategy.underline_to_camel) .setEntityTableFieldAnnotationEnable(true)//开启实体注解 .setRestControllerStyle(true)//rest格调controller .setChainModel(true)//链式setter .setSuperControllerClass(BaseController.class)//父类 .setSuperEntityClass(BaseEntity.class)//父类 .setControllerMappingHyphenStyle(true)//? .setTablePrefix("t_");//表名前缀 //4. 包名策略配置 PackageConfig pkConfig = new PackageConfig(); pkConfig.setParent("cn.qxstar.biz_service") .setMapper("mapper") .setService("service") .setServiceImpl("service.impl") .setController("controller") .setEntity("entity") .setXml("mapper.xml"); //5. 整合配置 AutoGenerator ag = new AutoGenerator(); ag.setGlobalConfig(config) .setDataSource(dsConfig) .setStrategy(stConfig) .setPackageInfo(pkConfig); //6. 执行 ag.execute(); }}

May 10, 2021 · 1 min · jiezi

关于mybatis-plus:第四阶段day02

SpringBoot高级用法1.1 对于配置文件的阐明1.1.1 properties配置文件阐明1.语法:key=value 构造2.properties中的属性值默认条件都是String类型 不须要增加引号 1.1.2 YML文件阐明1.语法: key: (空格)valueYml文件有父子级构造,采纳缩进的形式实现server: port: 80801.2 利用配置文件为属性赋值 (升高耦合性)1.2.1 XML形式为属性赋值1).编辑YML配置文件 为redis设置属性和属性值:redis.host: 127.0.0.1redis.port: 63791.2.2 properties形式为属性赋值1).定义properties文件 redis2.host=127.0.0.1redis2.port=63791.2.3 如果XML和Properties重名以谁为准YML形式为准, 注意事项:属性最好不要反复. 1.3 XML配置环境切换#筛选执行环境spring: profiles: actice: test(选用test环境配置) ---环境分割线#定义环境名称spring: profiles: test---环境分割线#定义环境名称spring: profiles: pord1.4 SpringBoot整合Mybatis1.4.1 导入jar包 <!--增加数据库驱动包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--springBoot整合jdbc--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--springBoot整合mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency>1.4.2 编辑YML配置文件# Spring整合Mybatis配置mybatis:type-aliases-package: com.jt.pojomapper-locations: classpath:/mybatis/mappers/*.xml#开启驼峰映射 configuration: map-underscore-to-camel-case: true1.4.3 编辑Mapper.xml映射文件<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 惟一确定Mapper接口的 肯定不能反复--><mapper namespace="com.jt.mapper.UserMapper"><!--定义别名包 type-aliases-package: com.jt.pojo 在程序执行时,如果定义了别名包则会主动的拼接门路 resultType="com.jt.pojo.User" 规定: 1.如果依据别名找不到则依据本人的定义查问类型 --><select id="findAll" resultType="User"> select * from user</select><!-- 开启驼峰映射规定的阐明 阐明:属性user_id 依据驼峰命名规定应该叫userId 例子: 1.user表: user_id user_name user_age 2.User对象: userId, userName userAge 驼峰命名规定 只有开启驼峰映射规定,则Mybatis会主动的实现映射. 原理: user_id(字段) ~~~去除两头的"_"线之后首字母大写 userId 将数据映射给属性userId(属性) 注意事项:一旦开启驼峰映射规定,则必须依照要求来写.--></mapper>MyBatisPuls1.1 ORM思维采纳对象的形式操作数据库 ...

November 25, 2020 · 1 min · jiezi

关于mybatis-plus:SpringBoot高级篇二MybatisPlusMP

MybatisPlus 介绍MyBatis-Plus(简称 MP)是一个 MyBatis 的加强工具,在 MyBatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。 MP的个性无侵入:只做加强不做扭转,引入它不会对现有工程产生影响,如丝般顺滑损耗小:启动即会主动注入根本 CURD,性能根本无损耗,间接面向对象操作弱小的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过大量配置即可实现单表大部分 CRUD 操作,更有弱小的条件结构器,满足各类应用需要反对 Lambda 模式调用:通过 Lambda 表达式,不便的编写各类查问条件,无需再放心字段写错反对主键主动生成:反对多达 4 种主键策略(内含分布式惟一 ID 生成器 - Sequence),可自在配置,完满解决主键问题反对 ActiveRecord 模式:反对 ActiveRecord 模式调用,实体类只需继承 Model 类即可进行弱小的 CRUD 操作反对自定义全局通用操作:反对全局通用办法注入( Write once, use anywhere )内置代码生成器:采纳代码或者 Maven 插件可疾速生成 Mapper 、 Model 、 Service 、 Controller 层代码,反对模板引擎,更有超多自定义配置等您来应用内置分页插件:基于 MyBatis 物理分页,开发者无需关怀具体操作,配置好插件之后,写分页等同于一般 List 查问分页插件反对多种数据库:反对 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库内置性能剖析插件:可输入 Sql 语句以及其执行工夫,倡议开发测试时启用该性能,能疾速揪出慢查问内置全局拦挡插件:提供全表 delete 、 update 操作智能剖析阻断,也可自定义拦挡规定,预防误操作 历史背景问题1: 当初操作的数据库任然采纳 sql语句的形式进行编辑. 操作sql的形式本质就是面对过程的操作形式.需要: 因为传统的sql 开发效率低,并且无论如许简略的sql都须要程序员本人编辑.很繁琐(无趣).想法: 是否以面向对象的形式操作数据库!!! ...

November 21, 2020 · 2 min · jiezi

关于mybatis-plus:MyBatisPlus系列之代码生成器

代码生成器,也叫逆向工程,是依据数据库里的表构造,主动生成对应的实体类、映射文件和接口。 这和hibernate的主动建表恰好相反。 很早之前,写了一个代码生成器的工程,本人也始终在用,很不便,也通过大量验证,也反对很多数据库。 看到很多小伙伴在为数据库生成实体类发愁,现分享给大家,进步开发效率。 mybatis-plus-code-generator 工程介绍工程地址:mybatis-plus-code-generator:https://github.com/fengwenyi/mybatis-plus-code-generator 目录构造: Config类针对每个人的习惯,能够在这个类里进行配置 /* 包名:service / public static final String PACKAGE_NAME_SERVICE = "repository"; /* 包名:service.impl / public static final String PACKAGE_NAME_SERVICE_IMPL = "repository.impl"; /* 包名:model / public static final String PACKAGE_NAME_MODEL = "entity"; /* 包名:dao / public static final String PACKAGE_NAME_DAO = "mapper"; /* 包名:xml / public static final String PACKAGE_NAME_XML = "xml"; /* 文件名后缀:Model / public static final String FILE_NAME_MODEL = "%sEntity"; /* 文件名后缀:Dao / public static final String FILE_NAME_DAO = "I%sMapper"; /* 文件名后缀:Mapper / public static final String FILE_NAME_XML = "%sMapper"; /* MP结尾,Service结尾 / public static final String FILE_NAME_SERVICE = "MP%sRepository"; /* 文件名后缀:ServiceImpl / public static final String FILE_NAME_SERVICE_IMPL = "%sRepositoryImpl"; /* 逻辑删除字段 / public static final String FIELD_LOGIC_DELETE_NAME = "delete_status"; /* 作者 / public static final String AUTHOR = "Erwin Feng"; /* 是否反对Swagger,默认不反对 / public static final Boolean SWAGGER_SUPPORT = false; ...

November 16, 2020 · 2 min · jiezi

关于mybatis-plus:MybatisPlus-page-源码

IPage外部原理也是基于拦截器,然而这个拦挡的是办法以及办法中的参数,这个也会判断是否是查问操作。 如果是查问操作,才会进入分页的解决逻辑。 进入分页逻辑解决后,拦截器会通过反射获取该办法的参数 进行判断是否存在IPage对象的实现类。如果不存在则不进行分页,存在则将该参数赋值给IPage对象。 而后进行拼接sql的解决实现分页操作。 然而应用IPage须要注入一个bean拦截器交给spring进行治理。如下。否则不会进行拦挡 注入paginationInterceptor 分页bean@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}拦挡源码public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget()); MetaObject metaObject = SystemMetaObject.forObject(statementHandler); // SQL 解析 this.sqlParser(metaObject); // 先判断是不是SELECT操作 (2019-04-10 00:37:31 跳过存储过程) MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); if (SqlCommandType.SELECT != mappedStatement.getSqlCommandType() || StatementType.CALLABLE == mappedStatement.getStatementType()) { return invocation.proceed(); } // 针对定义了rowBounds,做为mapper接口办法的参数 BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); Object paramObj = boundSql.getParameterObject(); // 判断参数里是否有page对象 IPage<?> page = null; if (paramObj instanceof IPage) { page = (IPage<?>) paramObj; } else if (paramObj instanceof Map) { for (Object arg : ((Map<?, ?>) paramObj).values()) { if (arg instanceof IPage) { page = (IPage<?>) arg; break; } } } /* * 不须要分页的场合,如果 size 小于 0 返回后果集 */ if (null == page || page.getSize() < 0) { return invocation.proceed(); } if (this.limit > 0 && this.limit <= page.getSize()) { //解决单页条数限度 handlerLimit(page); } String originalSql = boundSql.getSql(); Connection connection = (Connection) invocation.getArgs()[0]; if (page.isSearchCount() && !page.isHitCount()) { SqlInfo sqlInfo = SqlParserUtils.getOptimizeCountSql(page.optimizeCountSql(), countSqlParser, originalSql); this.queryTotal(sqlInfo.getSql(), mappedStatement, boundSql, page, connection); if (page.getTotal() <= 0) { return null; } } DbType dbType = Optional.ofNullable(this.dbType).orElse(JdbcUtils.getDbType(connection.getMetaData().getURL())); IDialect dialect = Optional.ofNullable(this.dialect).orElse(DialectFactory.getDialect(dbType)); String buildSql = concatOrderBy(originalSql, page); //执行物理分页 DialectModel model = dialect.buildPaginationSql(buildSql, page.offset(), page.getSize()); Configuration configuration = mappedStatement.getConfiguration(); List<ParameterMapping> mappings = new ArrayList<>(boundSql.getParameterMappings()); Map<String, Object> additionalParameters = (Map<String, Object>) metaObject.getValue("delegate.boundSql.additionalParameters"); model.consumers(mappings, configuration, additionalParameters); metaObject.setValue("delegate.boundSql.sql", model.getDialectSql()); metaObject.setValue("delegate.boundSql.parameterMappings", mappings); return invocation.proceed(); }参考博客`https://blog.csdn.net/xiaolegeaizy/article/details/108461284 ...

November 5, 2020 · 2 min · jiezi

关于mybatis-plus:Mybatis-Plus知识点快速抽取

初始化初始化初始化初始化初始化初始化

October 25, 2020 · 1 min · jiezi

关于mybatis-plus:mybatisplus学习整理

一、mybatis-plus简介:Mybatis-Plus(简称MP)是一个 Mybatis 的加强工具,在 Mybatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。二、springboot整合mybatis-plus:pom.xml: <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version></dependency><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope></dependency>$\color{red}{PS:集成mybatis-plus要把mybatis、mybatis-spring去掉,防止抵触}$mapper public interface UserMapper extends BaseMapper<User> {}test //批量查问测试~~~~@Testpublic void mybatisPlusTest() { List<User> users = userMapper.selectList(null); //Assert.assertEquals(5,users.size()); System.out.println(users);}@Testpublic void mybatisPlusTest() { User user = new User(); user.setName("东方不败"); user.setEmail("dfbb@163.com"); user.setId(1000L); user.setAge(20); System.out.println(userMapper.insert(user));//响应后果1,胜利}

October 14, 2020 · 1 min · jiezi

关于mybatis-plus:MyBatis-进阶MyBatisPlus基于-Springboot-演示

这一篇从一个入门的根本体验介绍,再到对于 CRUD 的一个具体介绍,在介绍过程中将波及到的一些问题,例如逐步策略,主动填充,乐观锁等内容说了一下,只选了一些重要的内容,还有一些没提及到,具体能够参考官网,简略的看完,其实会发现,如果遇到单表的 CRUD ,间接用 MP 必定难受,如果写多表,还是用 Mybatis 多点,毕竟间接写 SQL 会直观一点,MP 给我的感觉,就是办法封装了很多,还有一些算比拟是用的插件,然而可读性会略微差一点,不过集体有集体的认识哇,祝大家国庆高兴 ~ 一 引言最后的 JDBC,咱们须要写大量的代码来实现与根本的 CRUD ,或者会在肯定水平上应用 Spring 的 JdbcTemplate 或者 Apache 的 DBUtils ,这样一些对 JDBC 的简略封装的工具类。 再到后再应用 Mybatis 等一些优良的长久层框架,大大的简化了开发,咱们只须要应用肯定的 XML 或者注解就能够实现原来的工作 JDBC --> Mybatis 无疑简化了开发者的工作,而明天咱们所讲额 MyBatis-Plus 就是在 MyBatis 的根底上,更加的简化开发,来一起看看吧! 二 初识 MyBatis-Plus下列介绍来自官网: (一) 概述MyBatis-Plus(简称 MP)是一个 MyBatis 的加强工具,在 MyBatis 的根底上只做加强不做扭转,为简化开发、提高效率而生。 咱们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。 总之一句话:MyBatis-Plus —— 为简化开发而生! (二) 个性无侵入:只做加强不做扭转,引入它 不会 对现有工程产生影响,如丝般顺滑损耗小:启动即会主动注入根本 CRUD,性能根本无损耗,间接面向对象操作弱小的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过大量配置即可实现单表大部分 CRUD 操作,更有弱小的条件结构器,满足各类应用需要反对 Lambda 模式调用:通过 Lambda 表达式,不便的编写各类查问条件,无需再放心字段写错反对主键主动生成:反对多达 4 种主键策略(内含分布式惟一 ID 生成器 - Sequence),可自在配置,完满解决主键问题反对 ActiveRecord 模式:反对 ActiveRecord 模式调用,实体类只需继承 Model 类即可进行弱小的 CRUD 操作反对自定义全局通用操作:反对全局通用办法注入( Write once, use anywhere )内置代码生成器:采纳代码或者 Maven 插件可疾速生成 Mapper 、 Model 、 Service 、 Controller 层代码,反对模板引擎,更有超多自定义配置等您来应用内置分页插件:基于 MyBatis 物理分页,开发者无需关怀具体操作,配置好插件之后,写分页等同于一般 List 查问分页插件反对多种数据库:反对 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库内置性能剖析插件:可输入 Sql 语句以及其执行工夫,倡议开发测试时启用该性能,能疾速揪出慢查问内置全局拦挡插件:提供全表 delete 、 update 操作智能剖析阻断,也可自定义拦挡规定,预防误操作(三) 反对数据库mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、FirebirdPhoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库三 入门初体验依照官网的案例简略试一下 ,注:官网是基于 Springboot 的示例 ...

October 3, 2020 · 12 min · jiezi

关于mybatis-plus:Mybatisplus-之-selectPage分页查询

筹备工作做好间接进行分页查问 筹备工作在后面的文章中有提到过,不分明的能够翻看https://segmentfault.com/a/11... 1.新建配置文件 2.新建对象,封装查问后果 3.分页查问

September 25, 2020 · 1 min · jiezi

关于mybatis-plus:通过对象直接增删该查

@SpringBootTestclass SpringbootDemo2MybatisApplicationTests { @Autowired private UserDao userDao; @Test public void testFind(){ List<User> userList = userDao.findAll(); System.out.println(userList); } @Test public void testSelect01(){ List<User> userList = userDao.selectList(null); System.out.println(userList); } /** * 业务: 查问id=11的用户信息 主键... */ @Test public void testSelect02(){ User user = userDao.selectById(11); System.out.println(user); } /** * 业务: 查问name属性为"小乔"的数据 * sql: select * from user where name="小乔"; * 对象的形式 > sql形式 */ @Test public void testSelect03(){ //条件结构器 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "小乔"); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 业务: 查问name属性为"小乔"的数据 并且 age >=18岁 * sql: select * from user where name="小乔" and age>=18; * * 大于 > gt| 小于 < lt | * 大于等于 >= ge | 小于等于 le */ @Test public void testSelect04(){ //条件结构器 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "小乔") .ge("age", 18); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 业务: 查问name中蕴含 "精"的用户,并且sex为女 * 业务: 查问name中蕴含 以精结尾的数据,并且sex为女 * sql: select * from user where name like "%精%" and sex="女"; */ @Test public void testSelect05(){ //条件结构器 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.likeLeft("name", "精") .eq("sex", "女"); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 需要: 查问user表中的数据 要求依照年龄降序排列,如果年龄雷同依照id降序排列 */ @Test public void testSelect06(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("age","id"); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 需要: 查问name属性为null的数据. * where name is null */ @Test public void testSelect07(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.isNull("name"); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 查问name="小乔" age=17 性别=女的用户 * 如果传递的是对象.会依据对象中不为null的属性充当where条件. */ @Test public void testSelect08(){ User user = new User(); user.setName("小乔").setAge(17).setSex("女"); QueryWrapper<User> queryWrapper = new QueryWrapper<>(user); List<User> userList = userDao.selectList(queryWrapper); System.out.println(userList); } /** * 查问id=1,3,5,10数据. * sql: select * from user where id in (1,3,5,10) */ @Test public void testSelect09(){ //转化时,留神应用对象的类型 Integer[] ids = {1,3,5,10}; List<Integer> idList = Arrays.asList(ids); List<User> userList = userDao.selectBatchIds(idList); System.out.println(userList); } @Test public void testInsert(){ User user = new User(); user.setName("特朗普").setAge(70).setSex("男"); userDao.insert(user); } /** * 删除name=null的数据,或者name="特朗普" */ @Test public void testDelete(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.isNull("name") .or() .eq("name", "特朗普"); userDao.delete(queryWrapper); } /** * 案例1: 将id=1的数据的年龄改为8000岁. * sql1: update user set age=8000 where id=1; * 案例2: 要求将name="黑熊精" age=5500. * sql2: update user set age=5500 where name="黑熊精"; */ @Test public void testUpdate(){ User user = new User(); user.setId(1); //主键充当where条件 user.setAge(8000); userDao.updateById(user); //参数阐明 1.实体对象 封装set条件的值 // 2.更新条件结构器 User temp = new User(); temp.setAge(5500); UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("name", "黑熊精"); userDao.update(temp,updateWrapper); }}2.pojo层实现实现实现实现实现@Data@TableName //("user") //1.将对象与表 进行一对一关联public class User implements Serializable { @TableId(type = IdType.AUTO) //主键的信息 设定自增 private Integer Id; //@TableField("name") //如果字段名称与属性的名称统一(蕴含驼峰规定),能够省略不写 private String name; private Integer age; private String sex;}mapper层层层层层层层层层层层层层层层层层层层层层层层层层层层public interface UserDao extends BaseMapper<User> { ...

September 24, 2020 · 2 min · jiezi

关于mybatis-plus:MybatisPlus使用

简介业务场景mybatisplus该框架目标是帮忙咱们主动实现单表的CRUD; 介绍该框架指标是对mybatis框架只做加强不做扭转-->简化开发,提高效率 个性官网中个性如下: 原理原理-->以对象的形式操作数据库 实现: 利用注解实现对象与表绑定 属性与字段绑定.定义一个公共的Mapper接口,定义公共的CRUD操作 利用泛型辨别对象.依照特定的语法,将对象转化为sql语句:如下例:例子: 将user对象插入数据库中. userMapper.insert(user对象); //程序员实现的最初的代码 sql: insert into 表名(字段.....) values (属性值......); 由mp动静拼接之后交由mybatis执行.通过注解绑定,由底层生成表名(字段.....);传入属性值为为对象中的值;再由MP动静拼接之后交由mybatis执行. spring整合MP1.增加jar包依赖 <!--spring整合mybatis-plus 只导入MP包,删除mybatis包--><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version></dependency>增加MP的jar包后要将mybatis的jar包删除,MP中会蕴含mybatis,增加两个可能会抵触. 2.原理具体实现:1)编辑pojo类须要增加注解:@TableName("表名")--实现表与对象关联,如果pojo类名与表名统一(不辨别大小写),能够疏忽注解参数中表名@TableId(type = IdType.AUTO)--在主键属性上增加该注解,示意此属性为主键且主键自增(IdType次要用auto表主键自增/UUID表全局惟一) 2)Mapper接口继承BaseMapper<T>--留神理论利用时,泛型T的引入,写你所用的pojo类即可,不增加的话数据库不能实现操作 3)批改yml配置文件信息,将mybatis改为mybatis-plus即可,别的不须要更改,做到只加强不批改: mybatis-plus: #定义别名包 type-aliases-package: com.jt.pojo #增加xml文件的依赖 mapper-locations: classpath:/mybatis/mappers/*.xml #开启驼峰映射 configuration: map-underscore-to-camel-case: trueMP API应用以下别离是CRUD的常见API应用,具体阐明见官网和代码中注解--https://baomidou.com/ package com.jt.test;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.jt.mapper.UserMapper;import com.jt.pojo.User;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;import java.util.List;@SpringBootTestpublic class TestMybatis { @Autowired private UserMapper userMapper; //本地定义的findAll办法以及sql @Test public void test01(){ List<User> users = userMapper.findAll(); System.out.println(users); } //测试MP办法 @Test public void test02(){ //查问user表全副数据 List<User> users = userMapper.selectList(null); System.out.println(users); } /** * 1.测试入库 * 将用户信息 王大锤 20 男 入库 */ @Test public void insert(){ User user=new User(); user.setName("王大锤").setAge(20).setSex("男"); userMapper.insert(user); } /** * 2.查问练习 * 查问ID为21的用户 */ @Test public void select01(){ User user = userMapper.selectById(21); System.out.println(user); //查问记录总数 int count = userMapper.selectCount(null); System.out.println(count); } /** * 需要:查问性别为女,年龄大于100岁 * 条件结构器:动静拼接where条件的 多条件中默认的连接符and * 常见逻辑运算符 * 1.eq = 2.gt > 3.lt < * 4.ge >= 5.le <= */ @Test public void select03(){ QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("sex","女") .gt("age",100); List<User> users = userMapper.selectList(queryWrapper); System.out.println(users); } /** * 需要:1.查问名字中蕴含'精'字的男性 "%精%" * 2.查问以精结尾的 %精 * 3.查问以精结尾的 精% */ @Test public void select04(){ QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.likeLeft("name","精") //queryWrapper.like("name","精") .eq("sex","男"); List<User> users = userMapper.selectList(queryWrapper); System.out.println(users); } /** * 需要:查问sex=女 ,之后依照age倒序排列,如果年龄雷同依照id排列 */ @Test public void select05(){ QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("sex","女") .orderByDesc("age","id"); List<User> users = userMapper.selectList(queryWrapper); System.out.println(users); } /** * 需要:查问id为1,3,5,7,8,9的数据 * 关键字 in or * 在关联查问中慎用 */ @Test public void select06(){ Integer[] ids = {1,3,5,7,8,9}; List<Integer> list = Arrays.asList(ids); List<User> users = userMapper.selectBatchIds(list); System.out.println(users); } /** * 需要:删除id为53的数据 */ @Test public void delete01(){ userMapper.deleteById(53); } /** * 需要:批量删除id为1,2,3,4的数据 */ @Test public void delete02(){ Integer[] ids={1,2,3,4}; List<Integer> list = Arrays.asList(ids); userMapper.deleteBatchIds(list); } /** * 需要:删除age为30的男性 */ @Test public void delete03(){ QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("age","30") .eq("sex","男"); userMapper.delete(queryWrapper); } /** * 需要:将id为6的性别批改为女性 */ @Test public void update01(){ User user=new User(); user.setId(6).setSex("女"); userMapper.updateById(user); } /** * 需要:将name为悟空的角色名字改为卡卡罗特,性别改为男 */ @Test public void update02(){ User user = new User(); user.setName("卡卡罗特").setSex("男"); QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("name","悟空"); userMapper.update(user,queryWrapper); }}

August 27, 2020 · 2 min · jiezi

关于mybatis-plus:从零开始手写-mybatis四-mybatis-事务管理机制详解

前景回顾第一节 从零开始手写 mybatis(一)MVP 版本 中咱们实现了一个最根本的能够运行的 mybatis。 第二节 从零开始手写 mybatis(二)mybatis interceptor 插件机制详解 第三节 从零开始手写 mybatis(三)jdbc pool 从零实现数据库连接池 本节咱们一起来学习一下 mybatis 中的事务管理。 mybatis 中的事务管理mybatis 事务有两种应用形式: 应用JDBC的事务管理机制:即应用 java.Sql.Connection对象实现对事务的提交,回滚和敞开操作。应用MANAGED的事务管理机制:mybatis自身不会去实现事务管理的相干操作,而是交个内部容器来治理事务。当与spring整合应用后,个别应用spring来治理事务。事务工厂 TransactionFactory接口定义这个是对事务的一个工厂,接口如下: public interface TransactionFactory { /** * Sets transaction factory custom properties. * @param props */ void setProperties(Properties props); /** * Creates a {@link Transaction} out of an existing connection. * @param conn Existing database connection * @return Transaction * @since 3.1.0 */ Transaction newTransaction(Connection conn); /** * Creates a {@link Transaction} out of a datasource. * @param dataSource DataSource to take the connection from * @param level Desired isolation level * @param autoCommit Desired autocommit * @return Transaction * @since 3.1.0 */ Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);}次要就是如何依据一个 DataSource 创立一个 Transaction。 ...

July 19, 2020 · 6 min · jiezi