如果我们在现实生活中的软件项目中使用Spring Data Solr,很可能我们迟早会遇到一个要求,该要求指出我们的应用程序必须能够与本地Solr服务器和SolrCloud进行通信 。 目前,满足此要求意味着我们必须向所有Spring Data Solr存储库添加自定义方法。 这篇博客文章描述了如何做到这一点。
作为示例,我们将修改Spring Data Solr教程的上一部分的示例应用程序 。 在本博客中,我们将以某种方式更改该应用程序的自定义存储库实现,以将其所有方法都添加到所有存储库中。
注意:这当然是一个天真的示例,因为自定义接口及其实现都与TodoDocument类绑定。
我们可以按照以下步骤将自定义方法添加到所有存储库:
- 使用Maven获取所需的依赖项
- 创建一个声明自定义方法的接口。
- 实现创建的接口。
- 创建一个自定义存储库工厂bean。
- 将Spring Data Solr配置为使用自定义存储库工厂bean。
注意:这些博客文章提供了其他信息,可帮助我们理解此博客文章中描述的概念:
- 使用Maven运行Solr
- Spring Data Solr教程:Solr简介
- Spring Data Solr教程:配置
- Spring Data Solr教程:查询方法
- Spring Data Solr教程:将自定义方法添加到单个存储库
- Spring Data Solr教程:排序
- Spring Data Solr教程:分页
闲聊就够了。 让我们开始吧。
使用Maven获取所需的依赖关系
这篇博客文章的示例应用程序使用Spring Data Solr的构建快照,因为它为实现自定义存储库工厂bean提供了更好的支持。 我们可以通过对POM文件进行以下更改来获得所需的依赖关系:
- 将Spring快照存储库添加到pom.xml文件的存储库部分。
- 更改Spring Data Solr依赖项的版本。
在以下小节中将更详细地描述这些步骤。
使用Spring快照存储库
通过将以下存储库配置添加到我们的POM文件中,我们可以使用Spring快照Maven存储库:
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshot Maven Repository</name>
<url>http://repo.springsource.org/libs-snapshot</url>
</repository>
</repositories>
更新Spring Data Solr版本
通过将以下依赖项声明添加到pom.xml文件中,我们可以使用Spring Data Solr的构建快照。
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
创建自定义存储库界面
我们可以按照以下步骤为存储库创建一个自定义界面:
- 创建一个名为CustomBaseRepository的接口,该接口具有两个类型参数:文档类型( T )和文档ID ( ID )。
- 确保CustomBaseRepository接口扩展了SolrCrudRepository接口。
- 使用@NoRepositoryBean批注对接口进行批注。 这样可以确保Spring Data Solr不会尝试为我们的接口创建实现。
- 将count()和update()方法的方法声明添加到CustomBaseRepository接口。
CustomBaseRepository接口的源代码如下所示:
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.solr.repository.SolrCrudRepository;
import java.io.Serializable;
@NoRepositoryBean
public interface CustomBaseRepository<T, ID extends Serializable> extends SolrCrudRepository<T, ID> {
public long count(String searchTerm);
public void update(Todo todoEntry);
}
下一步是实现创建的接口。 让我们找出这是如何完成的。
实施自定义存储库界面
我们可以按照以下步骤实现自定义存储库:
- 创建一个名为CustomBaseRepositoryImpl的类。 此类具有两个类型参数:文档的类型( T )和文档的ID( ID )的类型。
- 确保创建的类扩展SimpleSolrRepository类并实现CustomBaseRepository接口。
- 创建一个构造函数,该构造函数将SolrOperations对象和文档类的类型作为构造函数参数。 该构造函数的实现只是调用超类的构造函数。
- 实现update()方法。 因为此博客文章中已描述了此方法的实现,所以在此不再赘述。
- 实现count()方法。 同样,由于在前面已经介绍了此方法的实现,因此在此不再赘述。
CustomBaseRepositoryImpl类的源代码如下所示:
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.PartialUpdate;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.repository.support.SimpleSolrRepository;
import java.io.Serializable;
public class CustomBaseRepositoryImpl<T, ID extends Serializable> extends SimpleSolrRepository<T, ID> implements CustomBaseRepository<T, ID> {
public CustomBaseRepositoryImpl(SolrOperations solrOperations, Class<T> entityClass) {
super(solrOperations, entityClass);
}
@Override
public long count(String searchTerm) {
String[] words = searchTerm.split(" ");
Criteria conditions = createSearchConditions(words);
SimpleQuery countQuery = new SimpleQuery(conditions);
return getSolrOperations().count(countQuery);
}
private Criteria createSearchConditions(String[] words) {
Criteria conditions = null;
for (String word: words) {
if (conditions == null) {
conditions = new Criteria("title").contains(word)
.or(new Criteria("description").contains(word));
}
else {
conditions = conditions.or(new Criteria("title").contains(word))
.or(new Criteria("description").contains(word));
}
}
return conditions;
}
@Override
public void update(Todo todoEntry) {
PartialUpdate update = new PartialUpdate("id", todoEntry.getId().toString());
update.add("description", todoEntry.getDescription());
update.add("title", todoEntry.getTitle());
getSolrOperations().saveBean(update);
getSolrOperations().commit();
}
}
让我们继续前进,了解如何创建自定义存储库工厂bean。
创建自定义存储库工厂Bean
存储库工厂bean是负责为存储库接口创建实现的组件。 因为我们要使用CustomBaseRepositoryImpl类作为Spring Data Solr存储库的实现,所以我们必须创建一个自定义存储库工厂bean。
我们可以按照以下步骤创建一个新的存储库工厂bean:
- 创建一个名为CustomSolrRepositoryFactoryBean的类,该类扩展了SolrRepositoryFactoryBean类。
- 将私有CustomSolrRepositoryFactory类添加到CustomSolrRepositoryFactory bean类。 该类扩展了SolrRepositoryFactory类,它具有两个类型参数:文档类型( T )和文档ID( ID )的类型。
- 重写SolrRepositoryFactoryBean类的doCreateRepositoryFactory()方法。 此方法的实现返回一个新的CustomSolrRepositoryFactory对象。
让我们仔细看看CustomSolrRepositoryFactory类的实现。 我们可以按照以下步骤实现它:
- 将一个SolrOperations字段添加到CustomSolrRepositoryFactory类。
- 将构造函数添加到CustomSolrRepositoryFactory类。 此类将使用的SolrOperations对象用作构造函数参数。 它的实现将仅调用超类的构造函数,并将接收到的SolrOperations对象设置为我们在第一步中创建的字段。
- 重写SolrRepositoryFactory类的getTargetRepository()方法并返回一个新CustomBaseRepositoryImpl对象。
- 重写SolrRepositoryFactory类的getRepositoryBaseClass()方法,并返回我们的自定义接口的类型。
而已。 我们的自定义存储库工厂bean的源代码如下所示:
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.repository.support.SolrRepositoryFactory;
import org.springframework.data.solr.repository.support.SolrRepositoryFactoryBean;
import java.io.Serializable;
public class CustomSolrRepositoryFactoryBean extends SolrRepositoryFactoryBean {
@Override
protected RepositoryFactorySupport doCreateRepositoryFactory() {
return new CustomSolrRepositoryFactory(getSolrOperations());
}
private static class CustomSolrRepositoryFactory<T, ID extends Serializable> extends SolrRepositoryFactory {
private final SolrOperations solrOperations;
public CustomSolrRepositoryFactory(SolrOperations solrOperations) {
super(solrOperations);
this.solrOperations = solrOperations;
}
@Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new CustomBaseRepositoryImpl<T, ID>(solrOperations, (Class<T>) metadata.getDomainType());
}
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return CustomBaseRepository.class;
}
}
}
我们的下一个步骤是配置Spring Data Solr以使用我们刚创建的存储库工厂bean。 让我们开始吧。
配置Spring Data Solr
我们的最后一步是将Spring Data Solr配置为使用上一步中创建的新存储库工厂bean。 我们可以通过使用Java配置类或XML配置文件来实现。 以下小节将介绍这两个选项。
注意:为了清楚起见,简化了以下小节中介绍的不同配置文件。 实际上,我们的示例应用程序在开发和生产环境中具有不同的配置 。
Java配置
如果使用Java配置,则可以通过使用@EnableJpaRepositories批注的repositoryFactoryBeanBeanClass属性,将Spring Data Solr配置为使用自定义存储库工厂bean。 配置类的源代码如下所示:
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;
@Configuration
@EnableSolrRepositories(
basePackages = "net.petrikainulainen.spring.datasolr.todo.repository.solr",
repositoryFactoryBeanClass = CustomSolrRepositoryFactoryBean.class
)
public class SolrContext {
//Configuration is omitted.
}
XML配置
当我们使用XML配置时,可以通过使用存储库名称空间元素的factory-class属性,将Spring Data Solr配置为使用自定义存储库工厂bean。 我们的应用程序上下文的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:solr="http://www.springframework.org/schema/data/solr"
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-3.2.xsd http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr.xsd">
<!-- Enable Solr repositories and configure repository base package -->
<solr:repositories base-package="net.petrikainulainen.spring.datasolr.todo.repository.solr"
factory-class="net.petrikainulainen.spring.datasolr.todo.repository.solr.CustomSolrRepositoryFactoryBean"/>
<!-- The configuration is omitted. -->
</Beans>
摘要
现在,我们创建了两个自定义方法,这些方法已添加到示例应用程序的所有存储库中。 当然,就像我们前面学到的一样,该示例没有任何意义,因为我们的自定义存储库接口及其实现与TodoDocument类相关。
本教程教了我们两件事:
- 我们可以使用@NoRepositoryBean批注向Spring Data Solr发信号, 通知它不应为使用@NoRepositoryBean批注的接口创建实现。
- 我们可以使用@EnableSolrRepositories批注的repositoryFactoryBeanBeanClass属性或存储库名称空间元素的factory-class属性来配置自定义存储库工厂bean。
与往常一样,此博客的示例应用程序可在Github上获得 。