Custom Spring Data JPA Repository Methods

Integrate Spring Data provided functionality with manually implemented custom methods in a single JPA repository. Provide custom repository code and integrate it with generic CRUD abstraction and query method functionality.

The Interface

We define an interface for the functionality that is to be implemented manually.

MayorRepository.java
package io.lishman.springdata.jpa.repository;

import org.springframework.data.repository.Repository;

import io.lishman.springdata.jpa.domain.Mayor;

public interface MayorRepository extends Repository<Mayor, Integer>,
                                          MayorRepositoryCustom {

    public Mayor findByName(String name);

}

The Implementation

Then we provide an implementation of this interface for our manually defined methods.

Note that neither the interface nor the class knows anything about Spring Data.

However, the name of this class is important as we will see next.

MayorRepositoryImpl.java
package io.lishman.springdata.jpa.repository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcOperations;

/* 
 * Spring will find this class because the name follows a convention of 
 * 
 *      <InterfaceName>Impl
 * 
 * An alternative would be to specify 
 * 
 *      @Repository("mayorRepositoryImpl")
 *      
 * then the class could be called anything.
 *  
 * However, in this case it would need to be picked up by a component scan.
 * 
 *      @ComponentScan(basePackageClasses=RepositoryPackage.class)
 */
public class MayorRepositoryImpl implements MayorRepositoryCustom {
    
    @Autowired private JdbcOperations operations;

    public int getNameLength(int mayorId) {
        String name = operations.queryForObject(
                "SELECT mayor_name FROM mayor WHERE mayor_id = ?", 
                String.class,
                mayorId);
        return name.length();
    }

}

The Repository

Now we define the repository by extending the manually implemented interface and the Repository interface.

Spring will use the name of this interface to search for a class called MayorRepositoryImpl (the class we saw in the previous step), and integrate the manually implemented methods with any query methods included on this interface.

MayorRepository.java
package io.lishman.springdata.jpa.repository;

import org.springframework.data.repository.Repository;

import io.lishman.springdata.jpa.domain.Mayor;

public interface MayorRepository extends Repository<Mayor, Integer>,
                                          MayorRepositoryCustom {

    public Mayor findByName(String name);

}