01.Spring Data 简介
what:是什么
- Spring Data是一个用于简化持久层数据访问的开源框架。
- 其主要目标是使得对数据的访问变得方便快捷。
- Spring Data可以极大的简化数据操作的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。
- 包括CRUD外,还包括如分页、排序等一些常用的功能,几乎可以节省持久层代码80%以上的编码工作量。
- Spring Data的官网:http://projects.spring.io/spring-data/
02.Spring Data ElasticSearch简介
what:是什么
- Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。
- Spring Data为Elasticsearch项目提供集成搜索引擎。
- Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
- 官方网站:http://projects.spring.io/spring-data-elasticsearch/
why:为什么使用
- 用来操作ElasticSearch的框架,使得开发更加便捷
03.环境搭建
实现步骤:
- 创建SpringBoot的项目:版本为
<version>2.1.9.RELEASE</version>
- 勾选starter依赖坐标
- 编写持久层接口GoodDao,编写pojo实体类
- 配置文件,集群配置,ElasticSearch服务地址http://127.0.0.1:9300
实现过程:
- 创建SpringBoot的项目!
- 勾选starter依赖坐标,依赖如下
<?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.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lxgzhw</groupId>
<artifactId>springdata_es_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springdata_es_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
编写持久层接口GoodDao,编写pojo实体类
package com.lxgzhw.dao;
public interface GoodDao {
}
pojo实体类,商品good:这里的索引名称不能是已存在的
package com.lxgzhw.pojo;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* 商品实体类
*
* @Document() 注解作用:定义一个索引库,一个类型
* indexName属性:指定索引库的名称
* type属性:指定类型名称
* shards属性:指定分片数
* replicas属性:指定复制副本数
*/
@Data
@Document(indexName = "lxgzhw1", type = "goods", shards = 5, replicas = 1)
public class Good {
private Long id;//商品的唯一标识
private String title;//标题
private String category;//分类
private String brand;//品牌
private Double price;//价格
private String images;//图片地址
//getter,setter,toString
}
配置文件:applacation.properties
- 集群配置,ElasticSearch服务地址http://127.0.0.1:9301
- 这里的集群名称和服务地址要与之前教程中配置的保持一致
# 配置集群名称
spring.data.elasticsearch.cluster-name=my-Elasticsearch
# 配置es的服务地址
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9301
04.创建和删除索引
几个用到的注解:
- @Document:声明索引库配置
- indexName:索引库名称
- type:类型名称,默认是“docs”
- shards:分片数量,默认5
- replicas:副本数量,默认1
- @Id:声明实体类的id
- @Field:声明字段属性
- type:字段的数据类型
- analyzer:指定分词器类型
- index:是否创建索引 默认为true
- store:是否存储 默认为false
实体类配置:
package com.lxgzhw.pojo;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* 商品实体类
*
* @Document() 注解作用:定义一个索引库,一个类型
* indexName属性:指定索引库的名称
* type属性:指定类型名称
* shards属性:指定分片数
* replicas属性:指定复制副本数
*/
@Data
@Document(indexName = "lxgzhw2", type = "goods", shards = 5, replicas = 1)
public class Good {
//必须有id,这里的id是全局唯一的标识,等同于es中的“_id”
@Id
private Long id;
/**
* type: 字段数据类型
* analyzer: 分词器类型
* index: 是否索引(默认值:true)
* store: 是否存储(默认值:false)
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;//标题
@Field(type = FieldType.Keyword)
private String category;//分类
@Field(type = FieldType.Keyword)
private String brand;//品牌
@Field(type = FieldType.Double)
private Double price;//价格
@Field(type = FieldType.Keyword, index = false)
private String images;//图片地址
//getter ,setter ,toString
}
测试类:Demo01IndexOperationTests.java
package com.lxgzhw;
import com.lxgzhw.pojo.Good;
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.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 创建索引
* 配置映射
* 删除索引
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo01IndexOperationTests {
//模板设计模式
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void createIndexAndPutMapping() {
elasticsearchTemplate.createIndex(Good.class);//创建索引
elasticsearchTemplate.putMapping(Good.class);//配置映射
}
//删除索引
@Test
public void deleteIndex() {
elasticsearchTemplate.deleteIndex(Good.class);
}
}
05.文档的常见增删改查
修改GoodDao接口:继承ElasticsearchRespository模板接口
package com.lxgzhw.dao;
import com.lxgzhw.pojo.Good;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface GoodDao extends ElasticsearchRepository<Good, Long> {
}
添加测试类:SpringdataEsGoodCRUDTests.java
package com.lxgzhw;
import com.lxgzhw.dao.GoodDao;
import com.lxgzhw.pojo.Good;
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.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsGoodCRUDTests {
//注入Good业务层实现类
@Autowired
private GoodDao goodDao;
/**
* 新增
*/
@Test
public void save() {
Good good = new Good();
good.setId(1l);
good.setTitle("小米手机");
good.setCategory("手机");
good.setBrand("小米");
good.setPrice(19999.0);
good.setImages("http://image.leyou.com/12479122.jpg");
goodDao.save(good);
}
//修改
@Test
public void update() {
Good good = new Good();
good.setId(1l);
good.setTitle("小米手机");
good.setCategory("手机");
good.setBrand("小米");
good.setPrice(9999.0);
good.setImages("http://image.leyou.com/12479122.jpg");
goodDao.save(good);
}
//删除
@Test
public void delete() {
Good good = new Good();
good.setId(1l);
goodDao.delete(good);
}
//根据id查询
@Test
public void findById() {
Good good = goodDao.findById(1l).get();
System.out.println(good);
}
//查询所有
@Test
public void findAll() {
Iterable<Good> goods = goodDao.findAll();
for (Good good : goods) {
System.out.println(good);
}
}
//批量新增
@Test
public void saveAll() {
List<Good> goodList = new ArrayList<>();
for (int i = 0; i < 500; i++) {
Good good = new Good();
good.setId((long) i);
good.setTitle("[" + i + "]小米手机");
good.setCategory("手机");
good.setBrand("小米");
good.setPrice(19999.0 + i);
good.setImages("http://image.leyou.com/12479122.jpg");
goodList.add(good);
}
goodDao.saveAll(goodList);
}
//分页查询
@Test
public void findByPageable() {
//设置排序(排序方式,正序还是倒序,排序的id)
Sort sort = new Sort(Sort.Direction.DESC, "id");
int currentPage = 2;//当前页
int pageSize = 100;//每页显示多少条
//设置查询分页
PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort);
//分页查询
System.out.println("分页数据:");
Page<Good> goodPage = goodDao.findAll(pageRequest);
for (Good good : goodPage.getContent()) {
System.out.println(good);
}
}
}
07.Search查询
what:是什么
- ElasticSearch的search方法中QueryBuilders,就是第一章中的查询对象构建对象QueryBuilders。
- QueryBuilders具备的能力,search方法都具备。
- 所以,在这里重复内容不赘述,仅举例term查询。
创建测试类:SpringdataEsSearchTests.java
package com.lxgzhw;
import com.lxgzhw.dao.GoodDao;
import com.lxgzhw.pojo.Good;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
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.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsSearchTests {
//注入Good业务层实现类
@Autowired
private GoodDao goodDao;
/**
* term查询
* search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
*/
@Test
public void termQuery() {
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
Iterable<Good> goods = goodDao.search(termQueryBuilder);
for (Good g : goods) {
System.out.println(g);
}
}
/**
* term查询加分页
*/
@Test
public void termQueryByPage() {
int currentPage = 0;
int pageSize = 5;
//设置查询分页
PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
Iterable<Good> goods = goodDao.search(termQueryBuilder, pageRequest);
for (Good g : goods) {
System.out.println(g);
}
}
}
08.自定义方法名称查询
what:是什么
- GoodsRepository提供了非常强大的自定义查询功能;只要遵循SpringData提供的语法,我们可以任意定义方法声明
- 查询语法:findBy+字段名+Keyword+字段名+…
Keyword | Sample | Elasticsearch Query String |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| findByNameEndingWith |
|
|
|
|
|
|
|
|
|
|
持久层接口:
package com.lxgzhw.dao;
import com.lxgzhw.pojo.Good;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* ElasticsearchRepository 持久层操作ElasticSearch的模板接口
*/
public interface GoodDao extends ElasticsearchRepository<Good, Long> {
/**
* 根据title和价格查询,and的关系
*/
List<Good> findAllByTitleAndPrice(String title, Double price);
/**
* 根据商品价格范围查询
* 最低价格lowPrice
* 最高价格highPrice
*/
List<Good> findByPriceBetween(Double lowPrice, Double highPrice);
}
添加测试类:SpringdataEsCustomMethodQueryTests.java
package com.lxgzhw;
import com.lxgzhw.dao.GoodDao;
import com.lxgzhw.pojo.Good;
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;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsCustomMethodQueryTests {
//注入Good业务层实现类
@Autowired
private GoodDao goodDao;
/**
* 根据标题及价格查询
* 要求价格等于20023且标题的内容包含小米关键词
*/
@Test
public void findAllByTitleAndPrice() {
String title = "小米";
Double price = 20023.0;
List<Good> goods = goodDao.findAllByTitleAndPrice(title, price);
for (Good g : goods) {
System.out.println(g);
}
}
/**
* 根据价格范围查询
* 要求商品价格再3000,到20000之间
*/
@Test
public void findPriceBetween() {
double lowPrice = 3000.0;//最低价
double highPrice = 20000.0;//最高价
List<Good> goods = goodDao.findByPriceBetween(lowPrice, highPrice);
for (Good g : goods) {
System.out.println(g);
}
}
}