• sort:表单模糊查询的三种简单方式(springboot-h2-mybatis)


    前几天运营提到说后台管理系统有几个地方想要模糊查询..

     

    想了下是简单的,就是要注意以前方法的被调用情况,进行增量改动,以免牵一发而动全身。整理一波记录下(本次案例是按名字模糊查询学生信息)。

    三种方式概览

    1. SQL 语句正常 like,service 层按需要添加 '%'
    2. SQL 使用 CONCAT 函数
    3. mybatis 的 bind 语法

    依旧使用H2数据库(>>springboot与H2数据库快速本地测试),初始化脚本配置一个简单的学生表,添几条记录。

    H2和mybatis相关配置

    1)maven依赖

    <dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.mybatis.spring.boot</groupId>
    			<artifactId>mybatis-spring-boot-starter</artifactId>
    			<version>2.0.1</version>
    </dependency>
    

    2)application.properties

    server.port=8091
    server.servlet.context-path=/tsa
    #spring.datasource.url=jdbc:h2:mem:test
    spring.datasource.url=jdbc:h2:~/test
    spring.datasource.driver-class-name=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=123456
    spring.datasource.schema=classpath:h2sql/schema.sql
    spring.datasource.data=classpath:h2sql/data.sql
    spring.h2.console.enabled=true
    #localhost:8080/projectName/h2-console
    spring.h2.console.path=/h2-console
    #mybatis.config-location=classpath:/mybatis-config.xml
    mybatis.mapper-locations=classpath:/sqlmap/*Mapper.xml
    mybatis.configuration.map-underscore-to-camel-case=true
    mybatis.type-aliases-package=com.hwc.tsa.bean
    logging.level.com.hwc.tsa.dao=debug
    logging.level.com.hwc.tsa.mapper=debug
    

    3)H2初始化脚本(学生表)

    h2sql/schema.sql

    drop table if exists student;
    create table student(	
    	id int unsigned not null auto_increment comment '自增主键', 
    	name varchar(20) not null comment '字典类型-关联字段',
    	age int unsigned not null comment '年龄',
    	
    	status tinyint not null default 1 comment '逻辑删除字段',
    	crt_time timestamp not null default CURRENT_TIMESTAMP comment '创建时间',
    	upd_time timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP comment '更新时间',
    	
    	PRIMARY KEY (id)
    );
    

    h2sql/data.sql

    insert into student(name, age) values ('菠萝包', 1);
    insert into student(name, age) values ('皮卡丘', 3);
    insert into student(name, age) values ('悟空', 35);
    insert into student(name, age) values ('悟饭', 21);
    insert into student(name, age) values ('克林', 37);
    insert into student(name, age) values ('弗利沙', 999);
    insert into student(name, age) values ('妙蛙种子', 3);
    insert into student(name, age) values ('杰尼龟', 2);
    insert into student(name, age) values ('小杰', 17);
    

    启动项目并检查项目结构

    本次不是在之前的demo项目上继续的,只需关注几个目标包(xxx.bean.entity,xxx.mapper、resources/sqlmap、resources/h2sql)就OK。

    1)先启动springboot项目,初始化H2数据库。

    启动项目:

     

    控制台连接H2数据库(>>springboot与H2数据库快速本地测试)检查数据初始化:

     

    2)建立相应的包和目录结构,使用mybatis逆向工具快速生成entity和mapper

    >>简单使用maven-mybatis插件逆向生成entity和Mapper

    结构图:

     

    方式1

    方式1即 SQL 部分只写简单的 like,在 service 层决定哪个字段需要模糊查(加上 '%')。

    StudentMapper 新增方法(按名字模糊查):

    /**
    	 * 表单模糊查询支持
    	 * @param record
    	 * @return
    	 */
    	List<Student> selectByFormLikeSelective(Student record);
    

    StudentMapper.xml 新增查询映射点:

    <select id="selectByFormLikeSelective" parameterType="student" resultMap="BaseResultMap">
     	select <include refid="Base_Column_List"/> from student 
     	<where>
     		<if test="name!=null and name!=''">
     	and name like #{name}
     	 	</if>
     	 	<if test="status!=null">
     	 		and status = #{status}
     	 	</if>
     	</where> 
    </select>
    

    编写测试类:

    @RunWith(SpringRunner.class)
    //不加载web环境,更快捷测试
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) 
    //@SpringBootTest
    public class MapperDaoTests {
    	private static final Logger logger = LoggerFactory.getLogger(MapperDaoTests.class);
    	
    	@Autowired
    	StudentMapper stuMapper;
    	
    	@Test
    	public void testStudentMapperLikeSelective() {
    		//模拟controller输入
    		Map<String, Object> map = new HashMap<>();
    		map.put("name", "悟");
    		Student stu = new Student();
    		BeanUtil.mapValueCopy2Bean(map, stu);
    		//模拟service处理
    		stu.setName("悟");
    		stu.setName(StringUtil.addLikeStringLR(stu.getName()));//两边加 %
    		//调用mapper(dao)
    		List<Student> stuList = stuMapper.selectByFormLikeSelective(stu);
    		//输出验证 预期2行
    		logger.info("stuList size is: {}", stuList.size());
    	}
    }
    

    JUnit 测试结果:

     

    方式2

    方式2则是使用 SQL 的 CONCAT 函数,直接在 SQL 中连接 '%' 。

    主流数据库都有 CONCAT 函数,另外 Oracle 还可以使用 || 符号更方便,但是为了通用性,建议使用 CONCAT 函数。

    修改方式1中的代码。

    test 方法中去掉/注掉加百分号行:

    //stu.setName(StringUtil.addLikeStringLR(stu.getName()));//两边加 %
    

    xml 中修改目标 like 处为:

    <if test="name!=null and name!=''">
     	<!-- and name like #{name} -->
     	and name like concat(concat('%', #{name}), '%')
    </if>
    

    测试结果(注意dao传入时是没有加百分号的):

     

    方式3

    方式3使用 mybatis 动态 sql 的 bind 语法,官方地址:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html。

    这样的好处是既不要改 service 代码,也不需要使用 CONCAT 函数拼接字段值,只需在 sql 语句块开始处定义属性绑定规则即可。

    Mapper.xml 修改:

    <select id="selectByFormLikeSelective" parameterType="student" resultMap="BaseResultMap">
     	<bind name="name" value="'%' + _parameter.getName() + '%'" />
     	select <include refid="Base_Column_List"/> from student 
     	<where>
     		<if test="name!=null and name!=''">
     	and name like #{name}
     	 	</if>
     	 	<if test="status!=null">
     	 		and status = #{status}
     	 	</if>
     	</where> 
    </select>
    

    运行截图:

     

    传入就是带百分号的,可以看出,这种方式其实就是方式1,只不过加 '%' 的事情,mybatis 帮我们做了。

    总结

    这三种方式都很简单,但是综合而讲,直男君推荐方式1,我们在 service 层自行决定哪个需要模糊查。方式2的话,SQL不简洁;方式3则没有通用性。

  • 相关阅读:
    android 服务与多线程
    “产品级敏捷” 的这条路; 逐步的形成一高效的产品开发生态系统
    hdoj 1116 Play on Words 【并查集】+【欧拉路】
    辛星跟您玩转vim第四节之操作文本内容
    UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP
    CMMI过程改进反例
    UVA 11077
    Yii 框架 URL路径简化
    交水费一波四折
    雷观(十五):提高生产力和程序员价值的2种方法
  • 原文地址:https://www.cnblogs.com/noodlerkun/p/10924719.html
Copyright © 2020-2023  润新知