hexagonal architecture with spring data

I'm a little confused about your question. You talk a lot about layers, while what I consider "the article" about hexagonal architecture uses that term (almost ?) exclusively for describing what not to do.

Spring Data fits nicely with the hexagonal approach: Entities form your core domain, repository interfaces form the database facing API. Note that the implementation (outside the core domain, mostly provided by Spring Data itself) depends on the interface, not the other way round). Services and/or Controler form one or more user-facing APIs.

There are some violations of the rules prescribed by the hexagonal architecture: The annotations on the entities and also on repositories. They are inside the core domain but depend on the usage/implementation of the database access by being part of JPA or Spring Data.

JPA itself violates the hexagonal architecture even further in that the behavior fo the persistence implementation might leak heavily into your domain because if you work with managed entities any change gets automatically tracked and eventually persisted without any call to the persistence API. Also, changes to the persistence layer like the configuration of the flush strategy might completely change the behavior of your API.


To add to Tom's answer, I found the following options:

  • Create an interface with the same construction that is done in spring data, the problem is that you have to do the cast in the service.
  • Create an abstract class that has undefined functions that give you the data, then in the spring service, inherit from that class and implement the functions with the jpa repository, the problem is that you would not have separated your repository from your service.
  • Do not create an interface for the repositories, create in the domain a class / interface that gives you the data (it would be your repository), that function is what you inherit in the service of spring that will have the figure of repository but not the annotation and there if you use the JPA repository, example.

Domain.Service uses Domain.Repository, Application.repository inherits from Domain.repository and uses a JPA Repository, Aplication.service inherits from Domain.service and uses Domain.repository

The problem with the previous one is the complexity and play with the injection of dependencies of spring for the service of the application

The other problem is the entities, in some projects I simply use the jpa, in another I made an interface only with the getters and setter, the latter is somewhat cumbersome


Here is a good article on how to connect your database to your application: http://www.dossier-andreas.net/software_architecture/ports_and_adapters.html

What you are trying to do is creating a 'secondary port' and 'secondary adapter'.

The 'secondary port' (= interface) describes what to do, but has no framework dependencies. The 'secondary adapter' (= implementation) uses the jpa-repositories.

A jpa-entity cannot be your domain. It describes how the data is stored in the database. So a jpa-entity cannot be used in the 'secondary port', only your domain.

The 'secondary adapter' will need to convert your domain to jpa-entities.

Be careful, though, if you really want to use the proper hexagonal architecture. The power of Hibernate, and later JPA, was that the jpa-entity is your domain. It makes things a lot simpler (and harder). By splitting your domain from your entities, you'll loose lazy-loading opportunities, clear transaction boundaries, orphan deletion, ... Maybe you should make a trade-of and putting jpa within the core-layer.

I hope you've found this helpfull