上篇: 我这样写代码,比直接运用 MyBatis 功率提高了 100 倍

欢迎大众号转载,但请转当时最新版并在显眼处标明作者注明出处。假如你喜爱本文也欢迎转发分享 ^_^

Bean Searcher 号称 任何杂乱的查询都能够 一行代码搞定实体类的定义,但 Mybatis Plus 似乎也有相似的动态查询功后端框架用,它们有怎样的差异呢?

差异一(根本)mybatis中$和井号区别

Mybatismysql安装 Plus 依赖 MyBatis, 功用 CRUD 都有,而 Bean Seracher 不依赖任何 ORM,只专注高档查询。

只有运用 MyBatis 的项目才会用 Mybatis Plus,而运用 Hibernate,Data Jdbmysql安装配置教程c 等其它 ORM 的人则无mysql数据库基础知识法运用 Mybatis Plus。可是这些项目都能够运用 Bean Smysql数据库命令大全e后端语言archer(可与任何 ORM 合作运用,也可单独运用)。

运用 Myb实体类型atis Plus 需求编写实体类 和 Mapp实体类的定义er 接口,而 Bean Se后端开发archer 只需后端开发工程师编写 实体类,无需编写任何接口。

这个差异意义其实不大,由于假如你用 Mybatis Plus,在增修正的时分仍是需求界说 Mapper 接口。

差异二(高档查询)

Mybatis Plus 的 字段运算符 是静态的,而 Bean Searcher 的是动态的。

字段事务的四个特性运算符指的是某字段参与条件时用的mysql数据库=> 亦或是 like 这些条件类型。
不只 Mybatis Plus,一般的传统 ORM 的字段运算符都是静态的,包括 Hibernate、Spring data jdbc、JOOQ 等。

下面举例后端开发说明。事务文书关于只有三个字段的简单实体类:

public class User {
    private long id;
    private String name;
    private int age;
    // 省掉 Getter Setter
}

1)运用 MyBatis Plus 查询:

依赖:

implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.2

首先要写一mybatis面试题个 Mapper 接口:

public interface UserMapper extends BaseMapper<User> {
}

然后在 Controller 里写查询实体类是什么接口:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
    @GetMapping("/mp")
    public List<User> mp(User user) {
        return userMapper.selectList(new QueryWrapper<>(user));
    }
}

此刻这个接口能够支撑 三个检索参数,id, name, agemybatis中$和井号区别,例如:

  • GET /user/mp? name=Jack查询 name等于Jack 的数据
  • GET /user/mp? age=20查询 age等于20 的数据

可是他们所能表达的联系都是等于,假如你还想查询age > 20的数据,则力不从心了,除非在实体类的 age 字段上加上一条注解:

@TableField(condition = "%s>#{%s}")
private int age;

但加了注解后,age 就只能表达大于的联系了,mybatis面试题不再能够表达 等于了。所以说,MyBatit Plus 的事务所字段运算符静态 的,不能由参数动态指定。

当然咱们能够在 Controller 里依据参数调用 QueryWrapper 的不同办法让它支撑,但这样代码就不只一行了,检索的需求越杂乱,需求编写的代码就越多了。

2)运用 Bean Searchermysql怎么读 查询:

依赖:

implementation 'com.ejlchina:bean-searcher-boot-starter:3.8.0'

不必编写任何接口,复用同一个实体类,直接进行查询:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private BeanSearcher beanSearcher;
    @GetMapping("/bs")
    public List<User> bs(@RequestParam Map<String, Object> params) {
        // 你是否对入参 Map 有成见?假如有,请耐性往下看,有方案
        return beanSearcher.searchList(User.class, params);
    }
}

此刻这MySQL个接口能够支撑的事务所是干什么的检索参数就十分多了:

  • GET /user/bmybatis工作原理s? name=Jack查询 name等于Jack 的数据
  • GET /user/bs? name=Jack & nmysql索引ame-ic=true查询 name等于Jack 时疏忽大小写
  • GET /user/bs? n实体类的定义ame=Jack & name-op=ct查询 name包括Jack 的数据
  • GET /user/bs? age=20查询 age等于20 的数据
  • GET /user/bs? age=20 & age-op=gt查询 age大于20 的数据
  • 等等…

能够看出,Bean Searcher对每后端语言个字段运用的运算符都能够由参数指mysql数据库基础知识定,它们是动态 的。

不管查询需求简单仍是杂乱,Controller 里都只需一行代码。
参数 xxx-op 能够传哪些值?参看这儿:bs.zhxumybatis框架.cn/guide/lates…

看到这儿,假如看的理解,应该有一半的读者开端感慨:好家伙,这不是把后端拼装查询条件的进程都甩给了事务的四个特性前端?谁用了这个结构,不mybatis怎么读会被前端打死吗?

哈哈,我是不是道出了你现在心里的主意?假如你真的如此想,请细心回看咱们正在讨论的主题:【高档查询】事务局是什么单位 假如 不能理解什么是高档查询,事务所所长的委托任务我再贴个图助你思考

最近火起的 Bean Searcher 与 MyBatis Plus 到底有啥差异?

当然也并不后端语言是一切的检索需求都如此杂乱,当时端不需求控制检索办法时,xxmybatis动态sqlx-op 参数 能够省掉,省掉时,默许表达的是 等于,假如你想表达 其它办法,只需一个注解即可,例如:

@DbField(onlyOn = GreaterThan.class)
private int age;

这时,当时端只传一个 age 参数时,履行的 SQL 条件便是 ag事务所e > ? 了,并且即使前端多传一个 age-op 参数,也不再起作用了。

这其实是条件约束,下文会继事务性工作是什么意思续讲到。

差异三(逻辑分组)

就上文mybatis注解所例的代码,除却运算符 动态 的差异,Mybatis Pmybatis工作原理lus 对接纳MySQL到的参数生成的条件 都是且的联系,而 Bean S后端框架earcher 默许也是且mybatis面试题,但支撑 逻辑分组。

再举例说mysql数据库明,假定查询条件为:

( name = Jack 并且 amysql基础命令ge = 20 ) 或许 ( age = 30 )

此刻,MyBatis Plus 的一行代码就力不从心了,但 Bean Searcher 的一行代码仍然管用,只需这样传参即可:

  • GET /user/bs? a.name=Jack & a.age=20 & b.age=30 & gexpr=a|b

这儿 Bean Searcher 将参数分为 a, b 两组,并用新参数 gexpr 来表达这两组之间的联系(ab)。

实践传参时gexpr的值需求URLEnc实体类是什么ode 编码一下: Umybatis工作原理RLEncode(‘a|b’) => ‘a%7Cb’,由事务文书于 HTTP 规定事务隔离级别参数在 URL 上后端语言不能够出现 | 这种特殊字符。当然假如你喜爱 POST, 能够将它放在报文体mybatis面试题里。

什么场景下合适运用此功用? 当遇见相似下图中的需求时,它将助你一招制敌:

最近火起的 Bean Searcher 与 MyBatis Plus 到底有啥差异?

分组功用十分强大,但如此杂乱的检索需求也的确稀有,这儿不再细述,详情可事务隔离级别阅:bs事务文书.zhxu.cn/事务所guide/lates…

差异四(多表联查)

在不写 SQL 的情况下,Mybatis Plus 的动态查询 仅限于 单表,而 Bean Searcher 单表 和 多表 都支撑的相同好。

这也是很重要的一点差异,由于大多数高档查询 场景都是需求联表 的。

当然有些人坚持用单表做查询,为了防止联表,后端工程师从而在主表中冗余了许多字段,这不只造成了 数据库存储空间压力急剧增加,还mysql基础命令让项目愈加难以保护。由于源数据一但改变,你有必要一起更新这些冗余的字段,只要漏了一处,BUG 就跳出来了。

仍是举个例子,某订单列表需求展现 订单号,订单金额,店肆名,买家事务所名 等信息,用 Bean Searcher 实体类能够这后端语言么写:

@SearchBean(
    tables = "order o, shop s, user u",  // 三表相关
    joinCond = "o.shop_id = s.id and o.buyer_id = u.id",  // 相相关系
    autoMapTo = "o"  // 未被 @DbField 注解的字段都映射到 order 表
)
public class OrderVO {
    private long id;         // 订单ID   o.id
    private String orderNo;  // 订单号   o.order_no
    private long amount;     // 订单金额 o.amount
    @DbField("s.name")
    private String shop;     // 店肆名   s.name
    @DbField("u.name")
    private String buyer;    // 买家名   u.name
    // 省掉 Getter Setter
}

有心的同学会注后端是什么工作意到,这个实体类的命名并不是 Order, 而是 OrderVO。这儿仅仅一个建议的命名,由于它是本mysql基础命令质上便是一个 VO(View Object),作用仅仅一个视后端工程师图实体类,MyBatis所以建议将它和一般的单表实体类放在不同的 pack事务性工作是什么意思age 下(这仅仅一个标准)。

然后咱们的 Controller 中仍然只需一实体类型行代码:

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private BeanSearcher beanSearcher;
    @GetMapping("/index")
    public SearchResult<OrderVO> index(@RequestParam Map<String, Object> params) {
        // search 办法一起会回来满意条件的总条数
        return beanSearcher.search(OrderVO.class, params);
    }
}

这就完成了一个支撑高档查询的 订单接口,它相同支后端开发需要学什么撑在上文差异二差异三中所展现的各种检索办法。

从本例能够看出,Bean Searcher 的检索成果是 VO 目标,而非一般的单表实体类(DTO),这 省去了 DTO 向 VO 的转化进程,它能够直接回来给前端。

差异五(运用场景)

业务性的接口用引荐运用 MyBatis Plus, 非业务的检索接口中引荐运用 Bean Searcher

  • 例如 创建订单接口,在这个接口内部相同有许多查询,比如你需求查询 店肆的是否已经打烊,商品的库存是否还满意等,这些查询场景,引mysql密码忘记了怎么办荐仍然运用 原有的 MyBatis Plus 或其它 ORM 就好,不必再用 Bean Seracher 了。

  • 再如 订单列表接口,纯查询,可能需求分页、排序、过滤等功用,此刻就实体类型可用 Bean Seracher 了。

网友疑问

1)这貌似开放很大的mysql数据库命令大全检索才能,危险可控吗?

Bean Searcher 默许对实体类中的每个字段都支撑了许mybatis中$和井号区别多种检索办法,可是咱们也能够对它进行约束。

条件约束

例如,User 实体类后端框架name 字段只允许 准确匹配 与 后模糊 查询,则在 name 字段上增加实体类的作用一个注解即可:

@DbField(onlyOn = {Equal.class, StartWith.class})
private String name;

再如:不允许 age 字段参与 where 条件,则能够:

@DbField(conditional = false)
private int age;

参阅:bs.zhxu.cn/guimysql基础命令de/lates…

排序约束

Bean Searcher 默许允许按一切字段排序,但能够在实体类里进行实体类是什么约束。例如,只允许按 age 字段降序排序:

@SearchBean(orderBy = "age desc", sortType = SortType.ONLY_ENTITY)
public class User {
    // ...
}

或许,制止运用排序:

@SearchBean(sortType = SortType.ONLY_ENTITY)
public class User {
    // ...
}

参阅:bs.zhxu.cn/guide/lates…

2)运用 Bean Searcher 后 Co事务性工作ntro后端是做什么的ller 的入参有必要是 Map 类型?

:这 并不是有必要的,仅仅 Bean Searcher 的检实体类索办法承受这个类型的参数罢了。假如你在 Controller 入参那里 用一个 POJO 来接纳也是能够的,只需求再用一个东西类把它转化为 Map 即可,只不过 平白多写了一个类 罢了,例如:

@GetMapping("/bs")
public List<User> bs(UserQuery query) {
    // 将 UserQuery 目标转化为 Map 再传入进行检索
    return beanSearcher.searchList(User.class, Utils.toMap(query));
}

这儿为什么不直接运用 User 实体类来接纳呢? 由于 Bean Searcher 默许支撑许多参数,而原有的 Usemysql怎么读r 实体类中的字段不够多,用它来接纳的话会有许多参数接纳不到。假如咱们的检索需求比较简单,不需求前端指定mysql安装那些参数,则能够直接运用 User 实体类来接纳。

这儿的 UserQuery 能够这么界说:

// 继承 User 里的字段
public class UserQuery extends User {
    // 附加:排序参数
    private String order;
    private String sort;
    // 附加:分页参数
    private Integer page;
    private Integer size;
    // 附加:字段衍生参数
    private String id_op;   // 由于字段命名不能有中划线,这儿有下划线代替
    private String name_op; // 前端传参的时分就不能传 name-op,而是 name_op 了
    private String name_ic;
    private String age_op;
    // 省掉其它附加字段...
    // 省掉 Getter Setter 办法
}

然后 Utils 东西类的 toMap 办法能够这样写(这个东西类是通用的):

public static Map<String, Object> toMap(Object bean) {
    Map<String, Object> map = new HashMap<>();
    Class<?> beanClass = bean.getClass();
    while (beanClass != Object.class) {
        for (Field field : beanClass.getDeclaredFields()) {
            field.setAccessible(true);
            try {
                // 将下划线转化为中划线
                Strubg name = field.getName().replace('_', '-');
                map.put(name, field.get(bean));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        beanClass = beanClass.getSuperclass();
    }
    return map;
}

这样就能够了,该接口仍然能mysql基础命令够支撑许多种检索办法:

  • GET /user/bs? name=Jack查询 name等于Jack 的数据
  • GET /user/bs? name=Jack & name_ic=true查询 name等于J事务ack 时疏忽大小写
  • GET /user/b事务的四个特性s? nam后端开发工程师e=Jack & name_op=c事务所所长npct查询 name包括Jack 的数据
  • GET /user/bs? age=20查询 age等于20 的数据
  • GET /user/bs? age=20 &am事务所p; age_op=gt查询 age大于20 的数据
  • 等等…

注意运用参数是 name_op,不再是 name-op

以上的办法应该满意了一些强迫症患者的期望,可是这样的价值是多写mybatis注解一个 UserQuery 类,这不由让咱们细想:这样做值得吗?

当然,写成这样是有一些好处的:

  • 便于参数校验
  • 便于生成接口文档

可是:

  • 这是一个 非业实体类的作用务性事务所是干什么的 的检索接口,mybatisplus参数校验真的那么必要吗?原本就能够无参恳求,参数传错了体系主动疏忽它是不是也能够?
  • 假如了解了 Bean Searche事务的四个特性r 参数规矩,实体类的定义是不是不必这个 UserQuery后端开发是干什么的也能够生成文档,或许在文档中一句话概括 该接mysql索引口是 Bean Searcher 检索接口,请按照规矩传递参数,是事务所所长的委托任务不是也行呢mysql数据库基础知识

所以,我的建议是:一切以真实需求为后端开发需要学什么原则,不要为了标准而去标准,莫名徒增代码。

看到这儿,你可能已经在心里预备了一大堆的话想要反驳我,别急,咱们先回忆一下前面的 [多表联查] 章节所提到的:

  • Bean Searcher 中的实体类(SearchBean),实践上是一mysql安装配置教程个能够 直接与 DB 有跨表映射联系 的VO(View Ojbect),它代表一种检索业务,在概念上它与传统 ORM 的实体类(Entity)或 域类(Domain)有着本质的差异!

这一句话,道出了 Be后端开发an Searche事务所r 的魂灵。它看似简单,实则难以悟mysql安装透。假如您不是那种千古稀有先天通灵的奇才,强后端工程师事务建议阅览官方文档的 介绍 > 规划思想(出发点)mysql密码忘记了怎么办 章节,那里有对这一句话的事务局是什么单位具体解说。

3事务所所长npc)想手动增加或修正参数,只能向 Mapput 吗?有没有高雅点mybatis框架写法?

答:当然有。Bean Searcher 供给了一个 参数构事务隔离级别建器,可让后后端框架端人员想手动增加或修正检索参数时运用。例如:

@GetMapping("/bs")
public List<User> bs(@RequestParam Map<String, Object> params) {
    params = MapUtils.builder(params)  // 在原有参数根底之上
        .field(User::getAge, 20, 30).op(Between.class) // 增加一个年纪区间条件
        .field(User::getName).op(StartWith.class) // 修正 name 字段的运算符为 StartWith,参数值仍是用前端传来的参数
        .build();
    return beanSearcher.searchList(User.class, params);
}

4)前端乱传参数的话,存在 SQL 注入危险吗?

答:不存在的,Bean Searcher 是一个 MySQL读 ORM,它也存在 目标联系映射,所传参数都是实体类内界说的 Java 属性名,而非数据库表里的字段名(当时端MySQL传递实体类未界说的字段参数时,会被主动疏忽)。

也能够说:检索参数与数据库表是解耦的

5)能够随意传参,会让用户获取本不该看到的数据吗?

答:不会的,由于用户 可获取数据最多的恳求便是无参恳求,用事务所是干什么的户测验的任何参数,都只会缩小数据规模,不可能扩展

假如想做 数据权限,依据不同的用户回来不同的数据:可在 参数过滤器 里为权后端开发限字段一致注入条件(前提是 实体类mysql数据库中得有一个数据权限字段,能够在基类中界说)。

6)功率虽有提高,但功能怎么呢?

前段时间又不少朋友看了这篇文章暗里问我 Bean Searc后端开发需要学什么her 的功能怎么,这个mybatisplus周末我就在家做了下比照测验,成果如下:mysql数据库命令大全

  • 比 Spring Dat实体类图a Jdbc 高mybatis注解 5 ~ 10
  • 比 Spring Data JPA 高 2 ~ 3
  • 比 原生 MyBatis 高 1 ~ 2
  • 比 MyBatis Plus 高 2 ~ 5

完整报告:

  • github.com/troyzhxu/be…
  • gitee.com/troyzhxu/be…

以上测验是基于 H2 内存数据库进行

测验源码地址,我们可自行测验比照mysql密码忘记了怎么办

  • github.com/事务隔离级别troyzhxu/be…
  • gitee.com/troyzhxu/be…

7)支撑哪些数据库呢?

只要支撑正常的 SQL 语法,都是支撑后端开发的,另外 Bean Searchermybatis怎么读 内置了四个方言完成:

  • 分页语法和 MySQL 相同的数据库,默许支撑
  • 分页语法和 PostgreSql 相同的数据库,选用 PostgreSql 方MyBatis言 即可
  • 分页语法和 Oracle 相同的数据库,选用 Oracle 方言 即可
  • 分页语法和 SqlServer(v2012+)后端需要学什么相同的数据库,选用 SqlS事务所是干什么的erver 方言 即可

假如mysql密码忘记了怎么办分页语法首创的,自界说一个方言,只需完成一个办法即可,参阅:高档 > SQL 方言章节。

总结

上文所述的各种差异,并不是说 MyBatis Plus 和 Bean Searcher 哪个好哪个不好,而是它们专注后端语言的领域 的确不相同(后端工程师BS 也不会代替 MP)。

Bean Searcher 在刚诞生的时分是专门用来处理那种特别杂乱的检索需求(如上文中的例图所示),一般都用在 办理后台 体系里。
但用着用着,咱们发现,对检索需求没那么杂乱的一般分页查询接口,Bean Searcher 也十分好用后端工程师
代码写起来比用传mysql索引统的 ORM 要简洁的多,只需一个实体类和 Controller 里的几行代码,ServiceDao 什么的全都消失了,并且它回来的成果便是 VO, 也 不需后端开发是干什么的求再做进一步的转化 了,能够直接回来给前端。

在项目中合作运用它们,业务中运用 MyBatis Plus,列表检索场景运mysql数据库命令大全用 Bean S后端是做什么的earcher,你将 如虎添翼

实践上,在旧项目中集成 Bean Searcher 愈加容易,已有的单表实体类都能直接复用,而多表相关的 VO 目标类也只需增加相应注解即可拥有强大的检索才能。
不管项目本来 ORM 用的是 MyBatis, MP, 仍是 Hibernate,Data Jdbc 等,也不管 Web 结构是 Spring Boot, Spring MVC 仍是 Grails 或 Jfinal 等,只要是 java 项目, 都能够用它,为体系赋能高档查询。

最后附上 Bean Searcher 的相关衔接:

  • Beamybatis注解n S后端开发需要学什么earcher 官方文档(十分具体)
  • 我这样写代码,比直接运用 MyBatmybatis一级缓存和二级缓存is 功率提高了 100 倍(入门体会)
  • GitHub 源码库房(点个Star 吧)
  • Gitee 源码库房(点个Stamybatis中$和井号区别r 吧)

假如觉得文事务所所长的委托任务本不错,着手mysql索引点个赞吧 ^_^

  • 兴趣小文:不痛的盲人(编mysql基础命令程感悟)
  • 十分好用且前端后通用的 HTTP 客户端