Spring Data – Add custom method to Repository

In this article, we will show you how to add a custom method to Spring Data JPA CrudRepository and MongoDB MongoRepository

1. CrudRepository

1.1 Review a CustomerRepository, we will add a custom method to this repository.

CustomerRepository.java

package com.mkyong.dao;

import com.mkyong.model.Customer;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

public interface CustomerRepository extends CrudRepository<Customer, Long> {

    List<Customer> findByEmail(String email);

    @Query("select c from Customer c where c.email = :email")
    Stream<Customer> findByEmailReturnStream(@Param("email") String email);
	
	// I have a complicated logic, no idea how to implement with @Query ...
}

1.2 Create an interface.

CustomerRepositoryCustomAbc.java

package com.mkyong.dao;

import com.mkyong.model.Customer;

import java.util.List;

public interface CustomerRepositoryCustomAbc {

    List<Customer> findByAVeryComplicatedQuery(Long id, String name, String address);

}

1.3 For implementation class, the class name is very strict, you need to follow the “core repository interface + Impl” pattern. Failed to follow this pattern will cause the “Spring property unable to find” error message.

CustomerRepositoryImpl.java

package com.mkyong.dao;

import com.mkyong.model.Customer;

import java.util.List;

public class CustomerRepositoryImpl implements CustomerRepositoryCustomAbc {

    @Override
    public List<Customer> findByAVeryComplicatedQuery(Long id, String name, String address) {

        //...

    }
}

1.4 Update CustomerRepository to extend the new CustomerRepositoryCustomAbc interface.

CustomerRepository.java

package com.mkyong.dao;

import com.mkyong.model.Customer;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

public interface CustomerRepository extends CrudRepository<Customer, Long>, CustomerRepositoryCustomAbc{

   //...
	
}

Done.

2. MongoRepository

2.1 Another example to add a new “update a particular field” method to MongoRepository

DomainRepository.java

package com.mkyong.domain;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.List;

public interface DomainRepository extends MongoRepository<Domain, Long> {

    Domain findByDomainAndIP(String domain, String ip);

    @Query("{domain: { $regex: ?0 } })")
    List<Domain> findCustomByRegExDomain(String domain);

	//how to update a particular field? save() is not what I want.
}

2.2 Custome interface.

DomainRepositoryCustomAnyName.java

package com.mkyong.domain;

public interface DomainRepositoryCustomAnyName {

    int updateDomainDisplayFlagOnly(String domain, boolean flag);

}

2.3 Custom implementation.

DomainRepositoryImpl.java

package com.mkyong.domain;

import com.mongodb.WriteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

//Impl postfix of the name on it compared to the core repository interface
public class DomainRepositoryImpl implements DomainRepositoryCustomAnyName {

    @Autowired
    MongoTemplate mongoTemplate;

    @Override
    public int updateDomainDisplayFlagOnly(String domain, boolean flag) {

        Query query = new Query(Criteria.where("domain").is(domain));
        Update update = new Update();
        update.set("display", flag);

        WriteResult result = mongoTemplate.updateFirst(query, update, Domain.class);

        if(result!=null)
            return result.getN();
        else
            return 0;

    }
}

2.4 Update DomainRepository to extend the new custom interface – DomainRepositoryCustomAnyName

DomainRepository.java

package com.mkyong.domain;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.List;

public interface DomainRepository extends MongoRepository<Domain, Long>, DomainRepositoryCustomAnyName {

    //...
	
}

Done.

References

  1. Spring Data – Custom implementations
  2. Spring Boot – Spring Data MongoDB Example

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
Harol
Guest
Harol

Hello Mr Mkyong, I have some difficulty to test this kind of custom implementation with JUnit Test, I got a NoSuchElementExeption. Is there anything I would be doing wrong?

Jaroslav Záruba
Guest
Jaroslav Záruba

I need Spring to auto-create implementations out of my @Repository interfaces, but I need to alter the delete method.
And this seems like exactly what I was looking for.
Thank you very much, sir :)