表單模糊查詢的三種簡單方式(springboot-h2-mybatis)

前幾天運營提到說後臺管理系統有幾個地方想要模糊查詢..html

 

想了下是簡單的,就是要注意之前方法的被調用狀況,進行增量改動,以避免牽一髮而動全身。整理一波記錄下(本次案例是按名字模糊查詢學生信息)。web

話很少說,快速開始!spring

三種方式概覽

  1. SQL 語句正常 like,service 層按須要添加 '%'
  2. SQL 使用 CONCAT 函數
  3. mybatis 的 bind 語法

依舊使用H2數據庫(>>springboot與H2數據庫快速本地測試),初始化腳本配置一個簡單的學生表,添幾條記錄。sql

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.propertiesspringboot

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初始化腳本(學生表)mybatis

h2sql/schema.sqlapp

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.sqlmaven

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則沒有通用性。

打完收工,歡迎踩點吐槽,推薦轉發收藏。

下節預告:Java8 新日期 API 梳理和實際業務使用。

相關文章
相關標籤/搜索