1、Bean Searcher 是什么?

Bean Searcher 是一个轻量级 数据库 条件检索引擎,它的作用是从已有的数据库表中检索数据,专注高级查询的只读 ORM,天生支持联表,免 DTO/VO 转换,使一行代码实现复杂列表检索成为可能!

2、为什么要使用 Bean Searcher

requirement
产品给你画了一张图,还附带了一些要求:

  • 检索结果分页展示
  • 可以按任意字段排序
  • 按检索条件统计某些字段值
    这时候,后台接口该怎么写???使用 Mybatis 或 Hibernate 写100行代码是不是还打不住?而使用 BeanSearcher,仅需一行代码便可实现上述要求!!!

3、架构设计图

architecture

4、与 Hibernate MyBatis 的区别

首先,Bean Searcher 并不是一个完全的 ORM 框架,它存在的目的不是为了替换他们,而是为了弥补他们在列表检索领域的不足。

下表列举它们之间的具体区别:

区别点Bean SearcherHibernateMyBatis
ORM只读 ORM全自动 ORM半自动 ORM
实体类可多表映射支持不支持不支持
字段运算符动态静态静态
CRUDOnly RCRUDCRUD

从上表可以看出,Bean Searcher 只能做数据库查询,不支持 增删改。但它的 多表映射机制动态字段运算符,可以让我们在做复杂列表检索时代码 以一当十,甚至 以一当百

更关键的是,它无第三方依赖,在项目中可以和 任意 ORM 配合 使用。

5、具体使用方法

5.1、导入依赖

<!-- Bean Searcher 核心依赖,任何框架都可使用该依赖 -->
<dependency>
    <groupId>cn.zhxu</groupId>
    <artifactId>bean-searcher</artifactId>
    <version>4.1.2</version>
</dependency>

5.2、配置数据源

  • 在spring核心配置文件加入
<!-- 声明 BeanSearcher 检索器,它查询的结果是 SearchBean 泛型对象 -->
<bean id="beanSearcher" class="cn.zhxu.bs.implement.DefaultBeanSearcher" p:sqlExecutor-ref="sqlExecutor"/>
<!-- 声明 MapSearcher 检索器,它查询的结果是 Map 对象 -->
<bean id="mapSearcher" class="cn.zhxu.bs.implement.DefaultMapSearcher" p:sqlExecutor-ref="sqlExecutor"/>
<bean id="sqlExecutor" class="cn.zhxu.bs.implement.DefaultSqlExecutor" p:dataSource-ref="dataSource">
    <!-- 配置慢 SQL 阈值 -->
    <property name="slowSqlThreshold" value="500"/>
</bean>

5.4 、编写实体类

  • Book.java
package com.llh.domain;

import cn.zhxu.bs.bean.DbField;
import cn.zhxu.bs.bean.SearchBean;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

/**
 * 
 * @TableName book
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@SearchBean(tables = "book b left join btype t on b.tid = t.tid",autoMapTo = "b")
public class Book implements Serializable {
    /**
     * 图书id
     */
    private Integer bid;

    /**
     * 图书名称
     */
    private String bname;

    /**
     * 图书价格
     */
    private Double price;

    /**
     * 发布日期
     */
    private Date publishdate;

    /**
     * 作者名称
     */
    private String author;

    /**
     * 备注
     */
    private String descp;

    /**
     * 图书类型id
     */
    private Integer tid;

    /**
     * 图书类型名称
     */
    @DbField("t.tname")    // 字段映射
    private String tname;

    private static final long serialVersionUID = 1L;
}
  • 本例是使用@SearchBean注解的tables属性实现左外连接,可以很容易的指定多张表的关联关系。
  • 本例实体类只是使用其中一种方式来进行关联,详情可以前往检索实体类了解

5.3、编写业务层

  • 因为是只读 ORM,不需要DAO层,编写查询所有方法接口
  • BookService.java
package com.llh.service;

import cn.zhxu.bs.SearchResult;
import com.llh.domain.Book;

import java.util.Map;

/**
 * User: lilinhan
 * DateTime: 2023/5/27 9:14
 */
public interface BookService {
      SearchResult<Book> getBooks(Map<String,Object> map);
}
  • 这里的返回值必须是 SearchResult,由于我们涉及到分页,方法里只需要传入一个map集合,就能实现查询所有功能了!点进去会有很多方法,自行研究吧
  • BookServiceImpl.java
package com.llh.service.Impl;

import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.SearchResult;
import com.llh.domain.Book;
import com.llh.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * User: lilinhan
 * DateTime: 2023/5/27 9:14
 */
@Service
public class BookServiceImpl implements BookService {
      // 注入 BeanSearcher
      @Autowired
      BeanSearcher beanSearcher;

      @Override
      public SearchResult<Book> getBooks(Map<String, Object> map) {
            return beanSearcher.search(Book.class,map);
      }
}

返回BeanSearchersearch方法,有两个参数:

  • beanClass – 要检索的 bean 类型
  • paraMap – 检索参数

传入实体类的 class 对象和map集合

5.4、编写测试类

  • TestBook.java
package com.llh.test;

import cn.zhxu.bs.operator.Between;
import cn.zhxu.bs.operator.Contain;
import cn.zhxu.bs.util.MapUtils;
import com.llh.domain.Book;
import com.llh.mapper.BookMapper;
import com.llh.service.BookService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: lilinhan
 * DateTime: 2023/5/26 9:27
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-ioc.xml")
public class TestBook {
      @Autowired
      BookService bookService;

      @Test
      public void testList() {
            Map<String, Object> map = MapUtils.builder()
                    .build();
            // 获取 SearchResult 方法的list集合
            List<Book> books = bookService.getBooks(map).getDataList();
            for (Book book : books) {
                  System.out.println(book);
            }
      }
}
  • 效果如下:
    testList

5.5、高级查询

  • 测试一下,图书名称里包含“十”、价格在100-300之间、按照价格降序排序、分页三条数据,结果如下:
    testCondition2
  • 可以发现,我们在没有写任何一条 SQL语句的时候,BeanSearcher 已经在内部为我们解析好了。这里面有很多很多约束,包括表约束字段约束参数约束..等等,甚至还有风控参数!你所能想到的所有sql条件,这里全都有!详情还是前往官网了解

6、浅浅总结一下

  • BeanSearcher 是个伟大的出现,为后端的程序猿们提供了太大的方便,从此不必再过于纠结前端传的参数,从而把重心放在业务逻辑代码上,极大的提高了工作效率!!!
标签:no tag
本文到此就结束啦
Last modification:March 25, 2024
如果觉得我的文章对你有用,请随意赞赏