⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/Solr/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labslab-66 目录。

原创不易,给点个 Star 嘿,一起冲鸭!

1. 概述

《芋道 Solr 极简入门》文章中,我们一起完成了 Solr 的学习,并完成了 Solr 服务的搭建。

本文,我们将使用 Spring Data Solr 实现 Solr 的增删改查等等操作。

FROM https://spring.io/projects/spring-data-solr

Spring Data for Apache Solr, part of the larger Spring Data family, provides easy configuration and access to Apache Solr Search Server from Spring applications. It offers both low-level and high-level abstractions for interacting with the store.

Derived queries and annotations for Solr specific functionality allow easy integration into existing applications.

2. 快速入门

示例代码对应仓库:lab-66-spring-data-solr

本小节,我们会使用 spring-boot-starter-data-solr 自动配置 Spring Data Solr。同时,编写相应的 Solr 的 CRUD 操作。最终项目如下图所示:

项目结构

2.1 引入依赖

pom.xml 文件中,引入相关依赖。

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>lab-66</artifactId>
<groupId>cn.iocoder.springboot.labs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>lab-66-spring-data-solr</artifactId>

<properties>
<!-- 依赖相关配置 -->
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
<!-- 插件相关配置 -->
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- 自动化配置 Spring Data Solr -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>

<!-- 方便等会写单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>

具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。

2.2 配置文件

application.yml 中,添加 Solr 配置,如下:

spring:
data:
# Spring Data Solr 配置项,对应 SolrProperties 配置类
solr:
host: 'http://127.0.0.1:8983/solr' # Solr 服务器地址

通过 spring.data.solr 配置项,设置 Solr 服务的地址。

2.3 SolrProductDO

创建 SolrProductDO 类。代码如下:

@SolrDocument(collection = "new_core")
public class SolrProductDO {

/**
* ID 主键
*/
@Id
@Indexed(name = "id", type = "int")
private Integer id;

/**
* SPU 名字
*/
@Indexed(name = "name", type = "string")
private String name;
/**
* 描述
*/
@Indexed(name = "description", type = "string")
private String description;
/**
* 分类编号
*/
@Indexed(name = "cid", type = "cid")
private Integer cid;
/**
* 分类名
*/
@Indexed(name = "category_name", type = "string")
private String categoryName;

// 省略 setting/getting 方法
}

① 在类上,添加 @SolrDocument 注解,通过 collection 属性设置使用的 Solr Core 的名字。

② 在 id 属性上,添加 @Id 注解,设置它是实体的主键。

③ 在每个属性上,添加 @Indexed 注解,通过 name 属性设置 Solr Field 的名字,通过 type 属性设置 Solr Field 的类型。

2.4 ProductRepository

创建 ProductRepository 接口。代码如下:

public interface ProductRepository extends SolrCrudRepository<SolrProductDO, Integer> {

}

继承 SolrCrudRepository 接口,第一个泛型设置对应的实体是 SolrProductDO ,第二个泛型设置对应的主键类型是 Integer。

① 因为实现了 SolrCrudRepository 接口,Spring Data Solr 会自动生成对应的 CRUD 等等的代码。😈 是不是很方便。

② SolrCrudRepository 类图如下:

SolrCrudRepository 类图

艿艿:如果胖友看过艿艿写的 《芋道 Spring Boot JPA 入门》 文章,会发现和 Spring Data JPA 的使用方式,基本一致。这就是 Spring Data 带给我们的好处,使用相同的 API ,统一访问不同的数据源。o( ̄▽ ̄)d 点赞。

2.5 Application

创建 Application 类,声明个 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class Application {
}

2.6 简单测试

创建 ProductRepositoryTest 测试类,我们来测试一下简单的 ProductRepository 的每个操作。代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ProductRepositoryTest {

@Autowired
private ProductRepository productRepository;

@Test // 插入一条记录
public void testInsert() {
SolrProductDO product = new SolrProductDO();
product.setId(1); // 一般 Solr 的 ID 编号,使用 DB 数据对应的编号。这里,先写死
product.setName("芋道源码");
product.setDescription("我只是一个描述");
product.setCid(2);
product.setCategoryName("技术");
productRepository.save(product);
}

// 这里要注意,如果使用 save 方法来更新的话,必须是全量字段,否则其它字段会被覆盖。
// 所以,这里仅仅是作为一个示例。
@Test // 更新一条记录
public void testUpdate() {
SolrProductDO product = new SolrProductDO();
product.setId(1);
product.setCid(2);
product.setCategoryName("技术-Java");
productRepository.save(product);
}

@Test // 根据 ID 编号,删除一条记录
public void testDelete() {
productRepository.deleteById(1);
}

@Test // 根据 ID 编号,查询一条记录
public void testSelectById() {
Optional<SolrProductDO> userDO = productRepository.findById(1);
System.out.println(userDO.isPresent());
}

@Test // 根据 ID 编号数组,查询多条记录
public void testSelectByIds() {
Iterable<SolrProductDO> users = productRepository.findAllById(Arrays.asList(1, 4));
users.forEach(System.out::println);
}

}

每个测试单元方法,胖友自己看看方法上的注释。具体的,胖友可以自己跑跑,妥妥的。

3. 基于方法名查询

示例代码对应仓库:lab-66-spring-data-solr

《芋道 Spring Boot JPA 入门》 文章的「4. 基于方法名查询」小节中,我们已经提到:

在 Spring Data 中,支持根据方法名作生成对应的查询(WHERE)条件,进一步进化我们使用 JPA ,具体是方法名以 findByexistsBycountBydeleteBy 开头,后面跟具体的条件。具体的规则,在 《Spring Data JPA —— Query Creation》 文档中,已经详细提供。如下:

关键字 方法示例 JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
  • 注意,如果我们有排序需求,可以使用 OrderBy 关键字。

下面,我们来编写一个简单的示例。

艿艿:IDEA 牛逼,提供的插件已经能够自动提示上述关键字。太强了~

因为 Spring Data Solr 是 Spring Data 体系中的一员,所以也能享受到基于方法名查询的福利。所以,我们在本小节中,我们也来尝试下。

我们会在「2. 快速入门」的示例代码对应仓库 lab-66-spring-data-solr 的基础上,进行本小节的示例。

3.1 ProductRepository02

创建 ProductRepository02 接口。代码如下:

public interface ProductRepository02 extends SolrCrudRepository<SolrProductDO, Integer> {

SolrProductDO findByName(String name);

}

3.2 简单测试

创建 ProductRepository02Test 测试类,我们来测试一下简单的 UserRepository02 的每个操作。代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ProductRepository02Test {

@Autowired
private ProductRepository02 productRepository;

@Test // 根据名字获得一条记录
public void testFindByName() {
SolrProductDO product = productRepository.findByName("芋道源码");
System.out.println(product);
}

}

每个测试单元方法,胖友自己看看方法上的注释。具体的,胖友可以自己跑跑,妥妥的。

4. 基于 @Query 自定义查询

示例代码对应仓库:lab-66-spring-data-solr

「2. 快速入门」「3. 基于方法名查询」小节中,我们实现的都比较比较的查询,一般能够解决绝大多数业务场景的需求。但是偶尔会有一些比较复杂的查询,可以通过 Spring Data Solr 提供的 @Query 注解,实现自定义查询。

下面,我们在「2. 快速入门」的示例代码对应仓库 lab-66-spring-data-solr 的基础上,进行本小节的示例。

4.1 ProductRepository03

创建 ProductRepository03 接口。代码如下:

public interface ProductRepository03 extends SolrCrudRepository<SolrProductDO, Integer> {

/**
* 根据 name 匹配商品名或者商品分类,获得符合的商品列表
*/
@Query("name:?0 OR category_name:?0")
List<SolrProductDO> findByCustomQuery(String name);

}

@Query 注解中,我们填写的就是在 Solr 运维界面中的查询语法。

4.2 简单测试

创建 ProductRepository03Test 测试类,我们来测试一下简单的 UserRepository03 的每个操作。代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ProductRepository03Test {

@Autowired
private ProductRepository03 productRepository;

@Test
public void testFindByCustomQuery() {
List<SolrProductDO> products = productRepository.findByCustomQuery("技术");
System.out.println(products.size());
}

}

每个测试单元方法,胖友自己看看方法上的注释。具体的,胖友可以自己跑跑,妥妥的。

5. SolrTemplate

在 Spring Data Solr 中,有一个 SolrTemplate 类,提供了 Solr 操作模板,方便我们操作 Solr。同时通过 SolrTemplate,可以实现 Solr 更加高级的功能,例如说高亮突出

具体的示例代码,艿艿先偷个小懒,胖友可以阅读《SolrTemplate 模板代码》文章。

666. 彩蛋

至此,我们已经完成了 Solr 的简单学习。因为艿艿项目中搜索的需求,都是使用 Elasticsearch,所以本文就写的相对比较简单一些啦,哈哈哈。

并且,艿艿也更加推荐 Elasticsearch 实现搜索的功能,因此推荐阅读《芋道 Spring Boot Elasticsearch 入门》文章。

文章目录
  1. 1. 1. 概述
  2. 2. 2. 快速入门
    1. 2.1. 2.1 引入依赖
    2. 2.2. 2.2 配置文件
    3. 2.3. 2.3 SolrProductDO
    4. 2.4. 2.4 ProductRepository
    5. 2.5. 2.5 Application
    6. 2.6. 2.6 简单测试
  3. 3. 3. 基于方法名查询
    1. 3.1. 3.1 ProductRepository02
    2. 3.2. 3.2 简单测试
  4. 4. 4. 基于 @Query 自定义查询
    1. 4.1. 4.1 ProductRepository03
    2. 4.2. 4.2 简单测试
  5. 5. 5. SolrTemplate
  6. 6. 666. 彩蛋