SpringData-整体介绍

Spring Data是一个用于简化数据库、非关系型数据库、索引库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持 map-reduce框架和云计算数据服务。Spring Data可以极大的简化JPA(Elasticsearch…)的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD 外,还包括如分页、排序等一些常用的功能。

Spring Data 的官网

Spring Data 常用的功能模块如下:

  • Spring Data JDBC
  • Spring Data JPA
  • Spring Data LDAP
  • Spring Data MongoDB
  • Spring Data Redis
  • Spring Data R2DBC
  • Spring Data REST
  • Spring Data for Apache Cassandra
  • Spring Data for Apache Geode
  • Spring Data for Apache Solr
  • Spring Data for Pivotal GemFire
  • Spring Data Couchbase
  • Spring Data Elasticsearch
  • Spring Data Envers
  • Spring Data Neo4j
  • Spring Data JDBC Extensions
  • Spring for Apache Hadoop

Spring Data Elasticsearch 介绍

Spring Data Elasticsearch基于Spring Data API简化 Elasticsearch 操作,将原始操作Elasticsearch 的客户端API进行封装。Spring Data为Elasticsearch 项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储索引库数据访问层。

Spring Data Elasticsearch 官网

SpringData-代码功能集成

1. 创建Maven项目

2. 修改pom文件,增加依赖关系

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <parent>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-parent</artifactId>
  9. <version>2.3.6.RELEASE</version>
  10. <relativePath/>
  11. </parent>
  12. <groupId>com.demo</groupId>
  13. <artifactId>SpringDataWithES</artifactId>
  14. <version>1.0.0-SNAPSHOT</version>
  15. <properties>
  16. <maven.compiler.source>8</maven.compiler.source>
  17. <maven.compiler.target>8</maven.compiler.target>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.projectlombok</groupId>
  22. <artifactId>lombok</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-devtools</artifactId>
  31. <scope>runtime</scope>
  32. <optional>true</optional>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-test</artifactId>
  37. <scope>test</scope>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-test</artifactId>
  42. </dependency>
  43. <dependency>
  44. <groupId>junit</groupId>
  45. <artifactId>junit</artifactId>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework</groupId>
  49. <artifactId>spring-test</artifactId>
  50. </dependency>
  51. </dependencies>
  52. </project>

3. 增加配置文件

  1. # es 服务地址
  2. elasticsearch.host=127.0.0.1
  3. # es 服务端口
  4. elasticsearch.port=9200
  5. # 配置日志级别,开启 debug 日志
  6. logging.level.com.atguigu.es=debug

4. Spring Boot 主程序

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. @SpringBootApplication
  4. public class MainApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(MainApplication.class, args);
  7. }
  8. }


5. 数据实体类

  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. import lombok.ToString;
  5. import org.springframework.data.annotation.Id;
  6. import org.springframework.data.elasticsearch.annotations.Document;
  7. import org.springframework.data.elasticsearch.annotations.Field;
  8. import org.springframework.data.elasticsearch.annotations.FieldType;
  9. @Data
  10. @NoArgsConstructor
  11. @AllArgsConstructor
  12. @ToString
  13. @Document(indexName = "shopping", shards = 3, replicas = 1)
  14. public class Product {
  15. //必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id"
  16. @Id
  17. private Long id;//商品唯一标识
  18. /**
  19. * type : 字段数据类型
  20. * analyzer : 分词器类型
  21. * index : 是否索引(默认:true)
  22. * Keyword : 短语,不进行分词
  23. */
  24. @Field(type = FieldType.Text, analyzer = "ik_max_word")
  25. private String title;//商品名称
  26. @Field(type = FieldType.Keyword)
  27. private String category;//分类名称
  28. @Field(type = FieldType.Double)
  29. private Double price;//商品价格
  30. @Field(type = FieldType.Keyword, index = false)
  31. private String images;//图片地址
  32. }

6. 配置类

  • ElasticsearchRestTemplate是spring-data-elasticsearch项目中的一个类,和其他spring项目中的 template类似。
  • 在新版的spring-data-elasticsearch 中,ElasticsearchRestTemplate 代替了原来的ElasticsearchTemplate。
  • 原因是ElasticsearchTemplate基于TransportClient,TransportClient即将在8.x 以后的版本中移除。所以,我们推荐使用ElasticsearchRestTemplate。
  • ElasticsearchRestTemplate基于RestHighLevelClient客户端的。需要自定义配置类,继承AbstractElasticsearchConfiguration,并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象。 ```java package org.springframework.data.elasticsearch.config;

import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;

/**

  • @author Christoph Strobl
  • @author Peter-Josef Meisch
  • @since 3.2
  • @see ElasticsearchConfigurationSupport */ public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport {

    //需重写本方法 public abstract RestHighLevelClient elasticsearchClient();

    @Bean(name = { “elasticsearchOperations”, “elasticsearchTemplate” }) public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) {

    1. return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter);

    } } 需要自定义配置类,继承AbstractElasticsearchConfiguration,并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象java import lombok.Data; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;

@ConfigurationProperties(prefix = “elasticsearch”) @Configuration @Data public class ElasticsearchConfig extends AbstractElasticsearchConfiguration{

  1. private String host ;
  2. private Integer port ;
  3. //重写父类方法
  4. @Override
  5. public RestHighLevelClient elasticsearchClient() {
  6. RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));
  7. RestHighLevelClient restHighLevelClient = new
  8. RestHighLevelClient(builder);
  9. return restHighLevelClient;
  10. }

}

  1. <a name="yZiSF"></a>
  2. ### 7. DAO 数据访问对象
  3. ```java
  4. import com.lun.model.Product;
  5. import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
  6. import org.springframework.stereotype.Repository;
  7. @Repository
  8. public interface ProductDao extends ElasticsearchRepository<Product, Long>{
  9. }

SpringData-集成测试-索引操作

1. 测试类

  1. import com.lun.model.Product;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. @RunWith(SpringRunner.class)
  9. @SpringBootTest
  10. public class SpringDataESIndexTest {
  11. //注入 ElasticsearchRestTemplate
  12. @Autowired
  13. private ElasticsearchRestTemplate elasticsearchRestTemplate;
  14. //创建索引并增加映射配置
  15. @Test
  16. public void createIndex(){
  17. //创建索引,系统初始化会自动创建索引
  18. System.out.println("创建索引");
  19. }
  20. @Test
  21. public void deleteIndex(){
  22. //创建索引,系统初始化会自动创建索引
  23. boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class);
  24. System.out.println("删除索引 = " + flg);
  25. }
  26. }

用Postman 检测有没有创建和删除。

  1. #GET http://localhost:9200/_cat/indices?v

SpringData-集成测试-文档操作

  1. import com.lun.dao.ProductDao;
  2. import com.lun.model.Product;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.data.domain.Page;
  8. import org.springframework.data.domain.PageRequest;
  9. import org.springframework.data.domain.Sort;
  10. import org.springframework.test.context.junit4.SpringRunner;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. @RunWith(SpringRunner.class)
  14. @SpringBootTest
  15. public class SpringDataESProductDaoTest {
  16. @Autowired
  17. private ProductDao productDao;
  18. /**
  19. * 新增
  20. */
  21. @Test
  22. public void save(){
  23. Product product = new Product();
  24. product.setId(2L);
  25. product.setTitle("华为手机");
  26. product.setCategory("手机");
  27. product.setPrice(2999.0);
  28. product.setImages("http://www.atguigu/hw.jpg");
  29. productDao.save(product);
  30. }
  31. //POSTMAN, GET http://localhost:9200/product/_doc/2
  32. //修改
  33. @Test
  34. public void update(){
  35. Product product = new Product();
  36. product.setId(2L);
  37. product.setTitle("小米 2 手机");
  38. product.setCategory("手机");
  39. product.setPrice(9999.0);
  40. product.setImages("http://www.atguigu/xm.jpg");
  41. productDao.save(product);
  42. }
  43. //POSTMAN, GET http://localhost:9200/product/_doc/2
  44. //根据 id 查询
  45. @Test
  46. public void findById(){
  47. Product product = productDao.findById(2L).get();
  48. System.out.println(product);
  49. }
  50. @Test
  51. public void findAll(){
  52. Iterable<Product> products = productDao.findAll();
  53. for (Product product : products) {
  54. System.out.println(product);
  55. }
  56. }
  57. //删除
  58. @Test
  59. public void delete(){
  60. Product product = new Product();
  61. product.setId(2L);
  62. productDao.delete(product);
  63. }
  64. //POSTMAN, GET http://localhost:9200/product/_doc/2
  65. //批量新增
  66. @Test
  67. public void saveAll(){
  68. List<Product> productList = new ArrayList<>();
  69. for (int i = 0; i < 10; i++) {
  70. Product product = new Product();
  71. product.setId(Long.valueOf(i));
  72. product.setTitle("["+i+"]小米手机");
  73. product.setCategory("手机");
  74. product.setPrice(1999.0 + i);
  75. product.setImages("http://www.atguigu/xm.jpg");
  76. productList.add(product);
  77. }
  78. productDao.saveAll(productList);
  79. }
  80. //分页查询
  81. @Test
  82. public void findByPageable(){
  83. //设置排序(排序方式,正序还是倒序,排序的 id)
  84. Sort sort = Sort.by(Sort.Direction.DESC,"id");
  85. int currentPage=0;//当前页,第一页从 0 开始, 1 表示第二页
  86. int pageSize = 5;//每页显示多少条
  87. //设置查询分页
  88. PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);
  89. //分页查询
  90. Page<Product> productPage = productDao.findAll(pageRequest);
  91. for (Product Product : productPage.getContent()) {
  92. System.out.println(Product);
  93. }
  94. }
  95. }

SpringData-集成测试-文档搜索

  1. import com.lun.dao.ProductDao;
  2. import com.lun.model.Product;
  3. import org.elasticsearch.index.query.QueryBuilders;
  4. import org.elasticsearch.index.query.TermQueryBuilder;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.data.domain.PageRequest;
  10. import org.springframework.test.context.junit4.SpringRunner;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class SpringDataESSearchTest {
  14. @Autowired
  15. private ProductDao productDao;
  16. /**
  17. * term 查询
  18. * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
  19. */
  20. @Test
  21. public void termQuery(){
  22. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
  23. Iterable<Product> products = productDao.search(termQueryBuilder);
  24. for (Product product : products) {
  25. System.out.println(product);
  26. }
  27. }
  28. /**
  29. * term 查询加分页
  30. */
  31. @Test
  32. public void termQueryByPage(){
  33. int currentPage= 0 ;
  34. int pageSize = 5;
  35. //设置查询分页
  36. PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
  37. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
  38. Iterable<Product> products =
  39. productDao.search(termQueryBuilder,pageRequest);
  40. for (Product product : products) {
  41. System.out.println(product);
  42. }
  43. }
  44. }