I'm going to start a new project to learn spring boot, spring data, and the hexagonal architecture. From my understanding the hexagonal architecture aims to separate the core or domain layer from the database operations (Infrastructure Layer). I have seen the following project structure for this architecture.
The Core Layer has:
Services-> Where the logic goes (interfaces and their implementations).
Entities -> These are going to be used in the entire application.
Repository-> Interfaces that the infrastructure layer has to implement.
The Infrastructure Layer has the implementation of the Repository interfaces, the JPA entities, calls made to the database (hibernate) and some sort of functions to transform the JPA entities to the Core Entities (mappers?).
Spring data has a very useful way to implement CRUD operations:
public interface UserRepository extends JpaRepository<User, Integer> {
}
However, I think if I use spring data, the JPA entities won't be part of the Infrastructure Layer if UserRepository is part of the Core Layer. This means that the Core entities would be useless. Should I create another UserRepository interface that belong to the Core Layer or Is there something I am missing?
UPDATE:
My concern using spring data comes from that I have to include the JPA entities inside the domain, which In theory would violate the hexagonal architecture.
So I was thinking to separate the domain Entities from the JPA entities. but If I do this I don't know where the repository of Spring Data should go and also find a way to transform the JPA entities into the Domain entities.
To ilustrate a little bit better I'm going to assume that I need to connect to a database from my application to read a users table.
This could be Domain Entity:
public class UserDomain{
private String name;
....//More fields, getters, and setters.
From my understanding, the services should include the logic and operates the Domain entities.
public interface UserService{
public void create(UserDomain user);
...
The implementation:
public class UserServiceImpl implements UserService{
public void create(UserDomain user) {
... //Calling the repository(Spring Data Repository?)
The above along with the repository interface is what I consider the Domain (If I'm wrong please correct me). Next, the infrastructure is composed by the JPA entities
@Entity
@Table(name="users")
public class User{
@Column(name="name")
private String name;
... // More Fields, getters, and setters
I think the interface in which I call Spring Data should be in the infrastructure part because later I need to map the JPA entities into the Domain entities and maybe I need to use yet another class (and adapter?) to do that mapping. Is this approach correct or Is there any other way? Sorry for the long post,I hope I have made myself clear.
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