4

I found out that there is an interface called GraphRepository. I have a repository for users implementing a homemade interface that does its job, but I was wondering, shouldn't I implement GraphRepository instead ? Even if it will be quite long to implement and some methods will be useless, I think it is a standard and I already re-coded a lot of methods that are defined in this interface.

So should I write "YAGNI" code or not respect the standard ? What is your advice ?

incomplete-co.de
  • 2,137
  • 18
  • 23

1 Answers1

11

you don't need to actually implement GraphRepository but extend it. the principals of Spring-Data is that all the boiler-plate CRUD code is taken care of (by proxying at startup time) so all you have to do is create an interface for your specific entity extending GraphRepository and then add only specific methods that you require.

for example; if i have an entity CustomerNode, to create standard CRUD methods, i can create a new interface CustomerNodeRepository extends GraphRepository<CustomerNode,Long>. all the methods from GraphRepository (e.g. save, findAll, findOne, delete, deleteAll, etc.) are now accessible from CustomerNodeRepository and implemented by Spring-Data-Neo4J without having to write a single line of implementation code.

the pattern now allows you to work on your specific repository code (e.g. findByNameAndDateOfBirth) rather than the simple CRUD stuff.

Spring-Data package is very useful for repository interaction. it can reduce huge amounts of code (have seen 80%+ reduction in code lines) and would highly recommend using it

edit: implementing custom execution

if you want to add your own custom behavior to a Repository method, you create the concept of merging interfaces and custom implementation. for example, lets say i want to create a method called findCustomerNodeBySomeStrangeCriteria and to do this, i actually want to link off to a relational database to perform the function.

first we define a separate, standalone interface that only includes our 'extra' method.

public interface CustomCustomerNodeRepository {
   List<CustomerNode> findCustomerNodeBySomeStrangeCriteria(Object strangeCriteria);
}

next we update our normal interface to extend not only GraphRepository, but our new custom one too

public interface CustomerNodeRepository extends GraphRepository<CustomerNode,Long>, CustomCustomerNodeRepository {

}

the last piece, is to actually implement our findCustomerNodeBySomeStrangeCriteria method

public class CustomerNodeRepositoryImpl implements CustomCustomerNodeRepository {

   public List<CustomerNode> findCustomerNodeBySomeStrangeCriteria(Object criteria) {
    //implementation code
}

}

so, there's a couple of points to note;

  • we create a separate interface to define any custom methods that have custom implementations (as distinct from Spring-Data compatible "findBy..." methods)
  • our CustomerNodeRepository interface (our 'main' interface) extends both the GraphRepository and our 'custom' one
  • we implement only the 'custom' method in a class that implements only the custom interface
  • the 'custom' implementation class must (by default) be called our 'main' interface Impl to be picked up by Spring Data (so in this case CustomNodeRepositoryImpl)

under the covers, Spring Data delivers a proxy implementation of CustomerNodeRepository as a merge of the auto-built GraphRepository and our class implementing CustomCustomerNodeRepository. the reason for the name of the class is to allow Spring Data to pick it up easily/successfully (this can be overwritten so it doesn't look for *Impl)

incomplete-co.de
  • 2,137
  • 18
  • 23
  • There's something that I don't get, I created an interface iUserRepository extending GraphRepository and a class Neo4jUserRepository implementing iUserRepository, but my IDE (IntelliJ) forces me to override all methods of GraphRepository (because they are abstracts), where am I wrong ? –  Jul 21 '13 at 15:17
  • 1
    the idea of Spring Data is that you don't actually implement the GraphRepository interface (either your extension or any other derivatives). there is a pattern for creating custom executions within the pattern and i can expand the answer to demonstrate if you like – incomplete-co.de Jul 21 '13 at 15:59
  • I would like. I found multiple examples on how it works, but I don't understand how it can compile if we do not implement abstract methods. –  Jul 21 '13 at 17:04
  • where are the abstract methods declared? in your custom or `GraphRepository`? – incomplete-co.de Jul 21 '13 at 17:32
  • Thanks for this precision but the point is that in your case CustomNodeRepositoryImpl implements CustomNodeRepository (which expands GraphRepository) so knowing that GrahpReposiroty methods are abstract, my code won't compile because I didn't override GraphRepository methods in CustomNodeRepositoryImpl. –  Jul 21 '13 at 17:35
  • Sorry I didn't see your comment. After verification GraphRepository is an interface so there is no abstract methods in it, my wrong. However, my problem is still the same, Intellij forces me to override many methods when I want to implement an interface that extends GraphRepository. A problem of dependency maybe ? –  Jul 21 '13 at 17:39
  • the trick is in which interface the custom class implements; it needs to implement `CustomCustomerNodeRepository` *only*. and `CustomCustomerNodeRepository` *should not* extend GraphRepository. Spring Data will merge the two classes later and inject into your `CustomerNodeRepository` bindings – incomplete-co.de Jul 21 '13 at 18:14