Spring Data JPA : Custom Repository / Query Methods Example

In this tutorial i am going to explain how to use query methods and custom repository implementation in Spring Data JPA framework. I have used Primfaces and JSF to develop the front end to access data using Spring Data infrastructure.

When you’re developing a Spring Data Repository, you’ll have three options:

  1. Using of a CRUD operations that implemented by the Spring Data infrastructure
  2. Defining of a query methods and
  3. Manually implementing your own custom repositories.

The following are the sections covered in this tutorial.

  1. Introduction
  2. Query Methods
  3. Spring Data Custom Repository
  4. Spring Configurations
  5. Persistence Entities
  6. Spring Service
  7. Primefaces / JSF Managed Bean
  8. JSF Configurations
  9. Maven Build
  10. Spring Data + Custom Repository + Query Methods Demo
  11. Database Table Queries
  12. Summary
  13. Download Source Code

1. Introduction

In our previous tutorials, we have explained the first option, in that, a vast amount of tutorials had used the infrastructure repositories. We have not explored any samples for the query methods and custom repository in our previous tutorials. In this tutorial, you would see how could we implement a Query methods and how to implement a custom repositories in spring data.

  • Spring Data provides the developers ability to define their own custom queries by declaring a method.
  • The method declaration will be inspected by the infrastructure and parsed, and a store-specific query was derived eventually.
  • However, as the queries become more complex, the method names would become awkwardly, until you’ve reached into level the keywords supported by the method parser wouldn’t even suffice.
  • Thus, Spring Data provides you a special annotation @Query that would take a query as a string that formed in the store-specific query language.

In this tutorial, we would use the MySQL as a persistent store, thus, JPA (Java Persistence API) & JPQL for defining the mapping and queries.

2. Query Methods

The query derivation mechanism built into the Spring Data repository infrastructure is useful to build constraining queries over entities of the repository. The below points represent the major points for creating a query method in your own repository.

  • Start the method name with one of the prefixes findBy, readBy and getBy.
  • Complete the method name by adding one or more of the entity’s properties and concatenate them with And and Or.
  • Operators like Between, LessThan, GreaterThan & Like are also applicable.
  • Define a nested properties is applicable (Employees have addresses).
  • Once you’ve finished writing your own query methods, a compilation error time could be raised if your query couldn’t be parsed.

Find below EmployeeRepository that we’ve defined in our previous tutorials. This time the repository has a set of query methods which derived from the Employee entity.

At the same time, a not valid query methods cause you will find an error like below:

Spring Data - Not Valid Query Methods

3. Spring Data Custom Repository

Until now, you’ve created repositories that exposed a CRUD methods or a query methods. Both types are implemented by the Spring Data infrastructure, either by a backing implementation (Repository proxy) or the query execution engine (Query Derivation). These two cases will probably cover a broad range of data access operations you’ll face when building applications. Often, it is necessary to provide a custom implementation for a certain repository methods.

Spring Data provides you an intelligent way to integrate your custom repository code and integrate it with the generic CRUD abstraction and query method functionality.

To enrich a repository with custom functionality you first define an interface and an implementation for the custom functionality. Use the repository interface you provided to extend the custom interface.


package net.javabeat.springdata.repo;

import java.util.List;

import net.javabeat.springdata.jpa.data.Employee;

public interface EmployeeRepositoryCustom {

	public List<Employee> readByEmployeeName(String name);



package net.javabeat.springdata.repo;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import net.javabeat.springdata.jpa.data.Employee;

public class EmployeeRepositoryImpl implements EmployeeRepositoryCustom{
	private EntityManager entityManager;

	public List<Employee> readByEmployeeName(String name) {
		return this.entityManager.
				createQuery("select e from Employee e where e.employeeName like '"+name+"'").


Your custom repository as you’ve seen doesn’t depend on the Spring Data, it’s like a normal Spring Bean. So it’s possible to contain an injection aspect or any other aspect you want supported by Spring framework. As you’ve noted the entityManager has been injected into our custom implementation.

After finished your custom repository and its implementation, it’s the time for you to upgrade your abstract repository (EmployeeRepository) so that it contains the custom behaviors. Just makes it extends another interface as below.


package net.javabeat.springdata.repo;

import java.util.List;

import net.javabeat.springdata.jpa.data.Employee;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

public interface EmployeeRepository extends CrudRepository<Employee, Integer>,EmployeeRepositoryCustom{

	public List<Employee> findByEmployeeName(String name);
	public List<Employee> getByEmployeeId(Integer id);
	public List<Employee> findByEmployeeNameAndEmployeeId(String name, Integer id);
	public List<Employee> findByEmployeeIdGreaterThan(Integer id);
	public List<Employee> findByEmployeeIdBetween(Integer lowerValue, Integer upperValue);
	public List<Employee> findByAddressAddressCountry(String country);
	public List<Employee> findAll();

For now, you’ve created your own custom repository and it’s implementation and added your custom behaviors into your original repository. But a big question here is, how could your custom repository been detected by the Spring Data specifically, we’ve not used any type of annotations related to neither inside the interface nor inside the implementation,  except that responsible for injecting the persistence context.

That’s what Spring Data called the configuration of the custom repositories, in that, if you use namespace configuration (XML Spring Bean Definition), the repository infrastructure tries to auto detect custom implementations by scanning for classes below the package we found a repository in. These classes need to follow the naming convention of appending the namespace element’s attribute repository-impl-postfix to the found repository interface name. This postfix defaults to Impl and for that our custom repository named as EmployeeRepositoryImpl.

4. Spring Configurations

Here is the complete Spring namespace configuration, meanwhile i’ll provide you a fragment of how the form of repository-impl-postfix attribute could be.


<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

	<!-- For consider the using of annotations foe defining Spring Bean -->
	<context:annotation-config />

	<!-- For defining Spring Bean -->
	<context:component-scan base-package="net.javabeat.springdata.beans" />

	<!-- For bootstrapping the Spring Repository -->
	<jpa:repositories base-package="net.javabeat.springdata.repo" />

	<!-- Necessary to get the entity manager injected into the factory bean -->
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

	<!-- Define EclipseLink JPA Vendor Adapter -->
	<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
		<property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform" />
		<property name="generateDdl" value="false" />
		<property name="showSql" value="true" />

	<!-- Entity Manager Factory -->
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="SpringData"></property>
		<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />

	<!-- Transaction Manager -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />

	<!-- Enable Transactional Manner -->
	<tx:annotation-driven transaction-manager="transactionManager" />


SpringContext.xml (Non defaulted postfix)

	<!-- For bootstrapping the Spring Repository -->
	<jpa:repositories base-package="net.javabeat.springdata.repo" repository-impl-postfix="DetectPostfixToken"/>

In case, you’ve provided the repository-impl-postfix attribute, you should comply when defining your custom repositories.

5. Persistence Entities

These are the entities used in this tutorial.


package net.javabeat.springdata.jpa.data;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity(name = "address")
public class Address {
	private Integer addressId;
	private String addressCountry = "";
	private String addressCity = "";

	@OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
	private Employee employee;

	public Employee getEmployee() {
		return employee;

	public void setEmployee(Employee employee) {
		this.employee = employee;

	public Integer getAddressId() {
		return addressId;

	public void setAddressId(Integer addressId) {
		this.addressId = addressId;

	public String getAddressCountry() {
		return addressCountry;

	public void setAddressCountry(String addressCountry) {
		this.addressCountry = addressCountry;

	public String getAddressCity() {
		return addressCity;

	public void setAddressCity(String addressCity) {
		this.addressCity = addressCity;


package net.javabeat.springdata.jpa.data;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

public class Employee {
	private Integer employeeId;

	@Basic(optional = false)
	private String employeeName;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "Address")
	private Address address = new Address();

	public Address getAddress() {
		return address;

	public void setAddress(Address address) {
		this.address = address;

	public Integer getEmployeeId() {
		return employeeId;

	public void setEmployeeId(Integer employeeId) {
		this.employeeId = employeeId;

	public String getEmployeeName() {
		return employeeName;

	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;

6. Spring Service

It’s just a bean used for referencing both of Spring Data default repository and that custom one. All of those methods contained in the custom repository are also contained in the Spring Data default repository, but the service below presents the concept of autowiring those custom repositories.


package net.javabeat.springdata.beans;

import net.javabeat.springdata.repo.EmployeeRepository;
import net.javabeat.springdata.repo.EmployeeRepositoryImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

public class RegistrationService {
	private EmployeeRepositoryImpl employeeRepositoryImpl;

	private EmployeeRepository employeeRepository;

	public EmployeeRepositoryImpl getEmployeeRepositoryImpl() {
		return employeeRepositoryImpl;

	public void setEmployeeRepositoryImpl(EmployeeRepositoryImpl employeeRepositoryImpl) {
		this.employeeRepositoryImpl = employeeRepositoryImpl;

	public EmployeeRepository getEmployeeRepository() {
		return employeeRepository;

	public void setEmployeeRepository(EmployeeRepository employeeRepository) {
		this.employeeRepository = employeeRepository;


7. Primefaces / JSF Managed Bean

It’s a managed bean for handling the presentation logic.


package net.javabeat.primefaces.managedbeans;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

import net.javabeat.springdata.beans.RegistrationService;
import net.javabeat.springdata.jpa.data.Employee;

import com.google.common.collect.Lists;

public class RegistrationManagedBean {

	private Employee employee = new Employee();

	private List<Employee> employees = new ArrayList<Employee>();

	public RegistrationManagedBean(){

	public void fetchEmployees(){
		this.employees = Lists.newArrayList(this.service.getEmployeeRepository().findAll());

	private RegistrationService service;

	public Employee getEmployee() {
		return employee;

	public void setEmployee(Employee employee) {
		this.employee = employee;

	public List<Employee> getEmployees() {
		return employees;

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;

	public RegistrationService getService() {
		return service;

	public void setService(RegistrationService service) {
		this.service = service;

	public String register(){
		this.employees = this.service.getEmployeeRepository().findAll();
		this.employee = new Employee();
		return "";

	public void findByEmployeeName(){
		this.employees = Lists.newArrayList(this.service.getEmployeeRepository().readByEmployeeName(this.employee.getEmployeeName()));

	public void findByEmployeeAddressAddressCountry(){
		this.employees = Lists.newArrayList(this.service.getEmployeeRepository().findByAddressAddressCountry(this.employee.getAddress().getAddressCountry()));



8. JSF Configurations

It’s faces configuration file that used for configuring the JSF framework in this tutorial.


<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2">

9. Maven Build

Here is the complete maven build file for downloading dependencies used for this tutorial.


<?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/maven-v4_0_0.xsd">






			<name>PrimeFaces Maven Repository</name>

		<!-- Servlet -->
		<!-- Faces Implementation -->
		<!-- Faces Library -->
		<!-- Primefaces Version 5 -->
		<!-- JSP Library -->
		<!-- JSTL Library -->
		<!-- Spring Core -->
		<!-- Spring Web -->
		<!-- Google List Library -->
		<!-- Dependencies for Eclipse JPA Persistence API -->
		<!-- Spring Data Dependency -->
		</dependency> <!-- Dependency for MySql Java connector -->


10. Spring Data + Custom Repository + Query Methods Demo

Spring Data - Custom Repository - Query Derivation - Demo

Spring Data - Custom Repository - Query Derivation - Demo II

Spring Data - Custom Repository - Query Derivation - Demo III

11. Database Tables Queries

Here is the database table creation and data population scripts used for populating sample data for this tutorial.

CREATE TABLE `address` (
  `addressId` bigint(20) NOT NULL AUTO_INCREMENT,
  `addressCountry` varchar(45) DEFAULT NULL,
  `addressCity` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`addressId`)
SELECT * FROM javabeat.employee;

CREATE TABLE `employee` (
  `employeeId` bigint(20) NOT NULL AUTO_INCREMENT,
  `employeeName` varchar(20) DEFAULT NULL,
  `address` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`employeeId`),
  KEY `FK_EMP_ADD` (`address`),

12. Summary

In this tutorial I have explained how to use the query methods and custom repository in Spring Data. This is useful when you want to define your own repository for your application. By looking at the above explanation, implementing custom repository is simple for the spring data developers. If you have any questions, please write it in the comments section. Please download the complete source code in the next section.

13. Download Source Code

Leave a Reply

Your email address will not be published. Required fields are marked *

Pin It on Pinterest

Share This

Share this post with your friends!