Backend Development 14 min read

Integrating Spring Data with Elasticsearch: Features, Use Cases, and Repository Loading Mechanism

The article explains how Spring Data provides a unified, Spring‑compatible data‑access layer for relational and NoSQL stores, illustrates its features and typical use cases, and walks through a practical Spring Data Elasticsearch integration—including configuration, entity and repository definitions—and details the dynamic proxy loading mechanism behind Spring Data repositories.

iQIYI Technical Product Team
iQIYI Technical Product Team
iQIYI Technical Product Team
Integrating Spring Data with Elasticsearch: Features, Use Cases, and Repository Loading Mechanism

Interacting with data storage systems is an essential part of backend web services. In the Java ecosystem, building a backend service with SSM (Spring+SpringMVC+MyBatis) or SSH (Spring+Struts+Hibernate) is common. MyBatis provides a powerful persistence layer, while Spring manages data source connections, transaction handling, and session lifecycle, allowing developers to focus on business logic.

With the rise of NoSQL systems, many scenarios benefit from using NoSQL databases (e.g., Redis, Couchbase, Elasticsearch, MongoDB, HBase) for higher storage capacity and faster query/update performance. However, integrating multiple NoSQL clients leads to fragmented configuration and API differences. A unified data access layer that abstracts these differences, offers a consistent CRUD API, and still exposes each store’s special features can greatly reduce development effort and improve code readability. For Java developers, such a layer should integrate smoothly with Spring.

This article introduces Spring Data as a data access framework and uses Spring Data Elasticsearch as an example to discuss four aspects:

Spring Data features

Application scenarios of Spring Data

Practical experience of integrating Spring Data

Loading principle of Spring Data Repository

What is Spring Data? Spring Data is an open‑source project under Spring that simplifies access to both relational and non‑relational data stores, supporting cloud services. It provides a consistent data‑access model while preserving each store’s specific capabilities. Sub‑projects include Spring Data Redis, Spring Data Elasticsearch, Spring Data Couchbase, etc.

Features of Spring Data

Most Spring Data modules offer three core capabilities:

Mapping between data structures and Java classes (similar to MyBatis models).

Repository interfaces (similar to MyBatis mapper interfaces).

Templating support for low‑level operations.

Repositories expose unified CRUD methods, conditional queries, sorting, and pagination, while still allowing store‑specific operations through the underlying Template.

Application scenarios

Spring Data is suitable for any Spring‑based project that interacts with relational databases or NoSQL stores. When a project needs to connect to multiple data stores, a single Repository API can handle basic CRUD across all stores, and the corresponding Template enables complex or store‑specific operations.

Practical integration example (Spring Data Elasticsearch)

1. Configure Elasticsearch in <!-- Declare Repository package --> <elasticsearch:repositories basepackage="com.qiyi.project.Repositories.es"/> <!-- Configure ES connection parameters --> <elasticsearch:transport-client id="client" clusternodes="${es.cluster.node}s}" cluster-name="${es.cluster.name}"/> <bean name="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"/> </bean>

2. Define an entity class:

@Document(indexName = "blog", type = "article")
public class Article {
    @Id
    private String id;
    private String title;
    @Field(type = FieldType.Nested)
    private List
authors;
}

3. Declare a Repository interface:

public interface ArticleRepository extends ElasticsearchRepository<Article, String> {
    List<Article> findByTitle(String title);
    // other CRUD methods are inherited
}

4. Use the Repository in a service:

@Autowired
private ArticleRepository articleRepository;

List<Article> articleList = articleRepository.findByTitle("XXX");

5. For custom queries, use the @Query annotation:

@Query("{\"constant_score\":{\"filter\":{\"bool\":{\"must\":[{\"term\":{\"title\":?0}}]}}}}")
List<Article> findByTitle(String title);

6. Alternatively, use the ElasticsearchTemplate directly:

CriteriaQuery criteriaQuery = new CriteriaQuery("title").is("XXX");
List<Article> articleList = elasticsearchTemplate.queryForList(criteriaQuery, Article.class);

Spring Data Repository loading principle

When the application starts, Spring scans the package defined in the elasticsearch:repositories tag, discovers Repository interfaces, and creates dynamic proxy instances for them. The key classes involved are RepositoryFactoryBeanSupport and RepositoryFactorySupport . The factory bean creates an ElasticsearchRepositoryFactory , which in turn generates proxy objects.

During proxy creation, QueryExecutorMethodInterceptor obtains a QueryLookupStrategy and resolves each query method. For Elasticsearch, two concrete RepositoryQuery implementations exist:

ElasticsearchStringQuery – handles methods annotated with @Query.

ElasticsearchPartQuery – handles derived query methods like findByTitle .

When a service calls a Repository method, the interceptor retrieves the corresponding RepositoryQuery from a cache and invokes its execute method, which performs the actual Elasticsearch operation.

Key code excerpt from RepositoryFactoryBeanSupport :

/** Returns the previously initialized repository proxy or creates and returns the proxy if previously uninitialized. */
private T initAndReturn() {
    Assert.notNull(repositoryInterface, "Repository interface must not be null on initialization!");
    if (this.repository == null) {
        this.repository = this.factory.getRepository(repositoryInterface, customImplementation);
    }
    return this.repository;
}

Key code excerpt from RepositoryFactorySupport (simplified):

public Object getRepository(Class
repositoryInterface, Object customImplementation) {
    // create dynamic proxy that delegates to QueryExecutorMethodInterceptor
}

Summary

As NoSQL systems evolve, backend services increasingly need to integrate multiple data stores. This article presented Spring Data’s features and use cases, demonstrated practical integration with Spring Data Elasticsearch, and briefly explained the internal loading mechanism of Spring Data Repository.

backendJavaElasticsearchNoSQLRepositorySpring Data
iQIYI Technical Product Team
Written by

iQIYI Technical Product Team

The technical product team of iQIYI

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.