什么是SpringData
Spring Data是一個用於簡化數據庫訪問,並支持雲服務的開源框架。其主要目標是使得對數據的訪問變得方便快
捷,並支持map-reduce框架和雲計算數據服務。 Spring Data可以極大的簡化JPA的寫法,可以在幾乎不用寫實現
的情況下,實現對數據的訪問和操作。除了CRUD外,還包括如分頁、排序等一些常用的功能。
Spring Data的官網:http://projects.spring.io/spring-data/
什么是SpringDataElasticSearch
Spring Data ElasticSearch 基於 spring data API 簡化 elasticSearch操作,將原始操作elasticSearch的客戶端API
進行封裝 。Spring Data為Elasticsearch項目提供集成搜索引擎。Spring Data Elasticsearch POJO的關鍵功能區域
為中心的模型與Elastichsearch交互文檔和輕松地編寫一個存儲庫數據訪問層。
官方網站:http://projects.spring.io/spring-data-elasticsearch/
創建工程並且實現使用SpringDataElasticSearch創建索引和文檔
第一步:創建一個maven工程,導入依賴
<dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.6.8</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.6.8</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.24</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.0.5.RELEASE</version> <exclusions> <exclusion> <groupId>org.elasticsearch.plugin</groupId> <artifactId>transport‐netty4‐client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.4.RELEASE</version> </dependency>
第二步:創建實體Article
基於spring data elasticsearch注解配置索引、映射和實體的
package com.wish.entity; 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 文檔對象 (索引信息、文檔類型) @Document(indexName = "blog3",type = "table03") public class Article { /* @Document(indexName="blob3",type="article"): indexName:索引的名稱(必填項) type:索引的類型 @Id:主鍵的唯一標識 @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type=FieldType.text) 每個文檔的字段配置(類型、是否分詞、是否存儲、分詞器 ) index:是否設置分詞 analyzer:存儲時使用的分詞器 searchAnalyze:搜索時使用的分詞器 store:是否存儲 type: 數據類型 */ @Id @Field(store = true,index = false,type = FieldType.Integer) private Integer id; @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text) private String title; @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text) private String content; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Table01{" + "id=" + id + ", title='" + title + '\'' + ", content='" + content + '\'' + '}'; } }
第三步:編寫dao層
package com.wish.dao; import com.wish.entity.Article; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> { }
第三步:編寫service
package com.wish.service; import com.wish.entity.Article; public interface ArticleService { public void save(Article article); }
第四步:編寫service的實現類
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.service.ArticleService; import org.springframework.beans.factory.annotation.Autowired;
@Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } }
第五步:配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd "> <!--掃描DAO包,自動創建實例--> <elasticsearch:repositories base-package="com.wish.dao"/> <!--掃描service包,創建service的實體--> <context:component-scan base-package="com.wish.service"/> <!--配置 ElasticSearch模的連接--> <elasticsearch:transport-client id="client" cluster-nodes="127.0.0.1:9300" cluster-name="my-elasticsearch"/> <!-- ElasticSearch模模板對象--> <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"></constructor-arg> </bean> </beans>
第六步:創建測試類SpringDataESTest
package com.wish; import com.wish.entity.Article; import com.wish.service.ArticleService; import org.elasticsearch.client.transport.TransportClient; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class SpringDataESTest { @Autowired private ArticleService articleService; @Autowired private TransportClient client; @Autowired private ElasticsearchTemplate elasticsearchTemplate; /** * 創建索引和映射 */ @Test public void createIndex() { elasticsearchTemplate.createIndex(Article.class); elasticsearchTemplate.putMapping(Article.class); } /** * 測試保存文檔 */ @Test public void saveArticle() { Article article = new Article(); article.setId(100); article.setTitle("測試SpringData ElasticSearch"); article.setContent("Spring Data ElasticSearch 基於 spring data API 簡化 elasticSearch操\n" + " 作,將原始操作elasticSearch的客戶端API 進行封裝\n" + " Spring Data為Elasticsearch Elasticsearch項目提供集成搜索引擎"); articleService.save(article); } }
創建索引和映射的效果和遇到錯誤
注意:如果創建時報一下錯誤
1.org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository - failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{-jhPfiM0Sh6cKPV4rCAKlg}{localhost}{127.0.0.1:9300}]
解決:(1)刪除掉data文件夾,進行重啟(2)注意配置文件中的cluster‐name的值與圖片中紅圈的一樣
2.org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.wish.SpringDataESTest': Unsatisfied dependency expressed through field 'articleService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.wish.service.ArticleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
解決:這個錯是因為一開寫着急了,service的實現類沒有用@service注解標識
創建文檔的效果
SpringDataElasticSearch的常用操作
增刪改查方法測試
修改service和service實現類
package com.wish.service; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; public interface ArticleService { //保存 public void save(Article article); //刪除 public void delete(Article article); //查詢全部 public Iterable<Article> findAll(); //分頁查詢 public Page<Article> findAll(Pageable pageable); }
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.service.ArticleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } @Override public void delete(Article article) { articleRepository.delete(article); } @Override public Iterable<Article> findAll() { Iterable<Article> iter = articleRepository.findAll(); return iter; } @Override public Page<Article> findAll(Pageable pageable) { return articleRepository.findAll(pageable); } }
增加文檔
/**測試保存*/ @Test public void save(){ Article article = new Article(); article.setId(1001); article.setTitle("elasticSearch 3.0版本發布"); article.setContent("ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的\n" + " 全文搜索引擎,基於RESTful web接口"); articleService.save(article); }
效果
修改文檔
/**測試更新*/ @Test public void update(){ Article article = new Article(); article.setId(1001); article.setTitle("[更新]elasticSearch 3.0版本發布"); article.setContent("[更新]ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的\n" + " 全文搜索引擎,基於RESTful web接口"); articleService.save(article); }
效果
刪除文檔
/**測試刪除*/ @Test public void delete(){ Article article = new Article(); article.setId(1001); articleService.delete(article); }
效果
批量添加文檔
/**批量插入*/ @Test public void save100(){ for(int i=1;i<=20;i++){ Article article = new Article(); article.setId(i); article.setTitle(i+"elasticSearch 3.0版本發布..,更新"); article.setContent(i+"ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用\n" + " 戶能力的全文搜索引擎,基於RESTful web接口"); articleService.save(article); } }
效果
分頁查詢文檔
/**分頁查詢*/ @Test public void findAllPage() { Pageable pageable = PageRequest.of(1, 10); Page<Article> page = articleService.findAll(pageable); for (Article article : page.getContent()) { System.out.println(article); } }
效果
常用查詢命名規則
帶條件查詢方法測試
修改dao層
package com.wish.dao; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.util.List; public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> { //根據標題查詢 List<Article> findByTitle(String condition); //根據標題查詢(含分頁) Page<Article> findByTitle(String condition, Pageable pageable); }
修改service層和service的實現層
package com.wish.service; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.List; public interface ArticleService { //保存 public void save(Article article); //刪除 public void delete(Article article); //查詢全部 public Iterable<Article> findAll(); //分頁查詢 public Page<Article> findAll(Pageable pageable); //根據標題查詢 List<Article> findByTitle(String condition); //根據標題查詢(含分頁) Page<Article> findByTitle(String condition, Pageable pageable); }
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.service.ArticleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } @Override public void delete(Article article) { articleRepository.delete(article); } @Override public Iterable<Article> findAll() { Iterable<Article> iter = articleRepository.findAll(); return iter; } @Override public Page<Article> findAll(Pageable pageable) { return articleRepository.findAll(pageable); } @Override public List<Article> findByTitle(String condition) { return articleRepository.findByTitle(condition); } @Override public Page<Article> findByTitle(String condition, Pageable pageable) { return articleRepository.findByTitle(condition,pageable); } }
帶條件查詢
/**條件查詢*/ @Test public void findByTitle(){ String condition = "版本"; List<Article> articleList = articleService.findByTitle(condition); for(Article article:articleList){ System.out.println(article); } }
效果
帶條件分頁查詢
/**條件分頁查詢*/ @Test public void findByTitlePage(){ String condition = "版本"; Pageable pageable = PageRequest.of(2,5); Page<Article> page = articleService.findByTitle(condition,pageable); int count=0; for(Article article:page.getContent()){ count++; System.out.println(article); } System.out.println("總記錄數:"+count); }
效果
使用Elasticsearch的原生查詢對象進行查詢
@Test public void findByNativeQuery() { //創建一個SearchQuery對象 SearchQuery searchQuery = new NativeSearchQueryBuilder() //設置查詢條件,此處可以使用QueryBuilders創建多種查詢 .withQuery(QueryBuilders.queryStringQuery("版本").defaultField("title")) //還可以設置分頁信息 .withPageable(PageRequest.of(1, 5)) //創建SearchQuery對象 .build(); //使用模板對象執行查詢 elasticsearchTemplate.queryForList(searchQuery, Article.class).forEach(article -> System.out.println(article)); }
效果