Skip to main content
added 60 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72

Right. This's, essentially, the basic design by segregation of concernslayers proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories, these are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but. Repositories tho add other abstractions like queries or criteria to enhance the support of queries and criteriadata access.

The RepositoryRepository is already an abstraction in between services and data stores. When we extend Spring Data JPA repository interfaces, we are implementing this design implicitly. When we do this, we are paying a tax: a tight coupling with Spring's components. Additionally, we break LoD and YAGNI by inheriting several methods we might not need or wish not to have. Not to mentionMoreover, we are (implicitly) assuming that such an interface doesn't provide us with any valuable insight aboutthe persistence data model is also the domain needs they servedata model. This is quite the endemic of Spring, after many years working with Spring frameworks, you end up making everything data-centric.

That said, extending Spring Data JPA repositories is not mandatory and you can avoid these tradeoffs by implementing. We implement a more plain and custom hierarchy of classes.

Back to the question, whether you should add one more abstraction layer, I would say no, because it's not necessary. Your example is only addingdon't think you need more complexitylayers. The layer you propose is going to end up as a proxy in between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place code you are not sure whether it belongs to the business or to the persistence.

Right. This's the basic design by segregation of concerns proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but the support of queries and criteria.

The Repository is already an abstraction in between services and data stores. When we extend Spring Data JPA repository interfaces, we are implementing this design implicitly. When we do this, we are paying a tax: a tight coupling with Spring's components. Additionally, we break LoD and YAGNI by inheriting several methods we might not need or wish not have. Not to mention that such an interface doesn't provide us with any valuable insight about the domain needs they serve.

That said, extending Spring Data JPA repositories is not mandatory and you can avoid these tradeoffs by implementing a more plain and custom hierarchy of classes.

Back to the question, whether you should add one more abstraction layer, I would say no, because it's not necessary. Your example is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

Right. This's, essentially, the design by layers proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories, these are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1. Repositories tho add other abstractions like queries or criteria to enhance the data access.

The Repository is already an abstraction in between services and data stores. When we extend Spring Data JPA repository interfaces, we are implementing this design implicitly. When we do this, we are paying a tax: a tight coupling with Spring's components. Additionally, we break LoD and YAGNI by inheriting several methods we might not need or wish not to have. Moreover, we are (implicitly) assuming that the persistence data model is also the domain data model. This is quite the endemic of Spring, after many years working with Spring frameworks, you end up making everything data-centric.

That said, extending Spring Data JPA repositories is not mandatory. We implement a more plain and custom hierarchy of classes.

Back to the question, I don't think you need more layers. The layer you propose is going to end up as a proxy in between services and repositories or as a pseudo-service-repository where to place code you are not sure whether it belongs to the business or to the persistence.

deleted 10 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but the support of queries and criteriascriteria.

    @Repository
    public class MyRepositoryImplDBRepository implements MyRepository{
        private EntityManager em;
        
        @Autowire
        public MyRepository (EntityManager em){    
             this.em = em;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class MyRepositoryImplWebRepository implements MyRepository{
        private RestTemplate rt;
    
        @Autowire 
        public MyRepositoryWebRepository (RestTemplate rt){    
             this.rt = rt;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class MyRepositoryImplFileRepository implements MyRepository{
       
        private File file; 
        public MyRepositoryFileRepository (File file){    
            this.file = file;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class MyRepositoryImplWSRepository implements MyRepository{
       
        private MyWebServiceClient wsClient; 

        @Autowire
        public MyRepositoryWSRepository (MyWebServiceClient  wsClient){    
               this.wsClient = wsClient;
        }

        //Interface implentation
        //...
    }

Back to the question, whether you should add one more abstraction layer, I would say no, because it's not necessary. Your example is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but the support of queries and criterias.

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private EntityManager em;
        
        @Autowire
        public MyRepository (EntityManager em){    
             this.em = em;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private RestTemplate rt;
    
        @Autowire 
        public MyRepository (RestTemplate rt){    
             this.rt = rt;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private File file; 
        public MyRepository (File file){    
            this.file = file;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private MyWebServiceClient wsClient; 

        @Autowire
        public MyRepository (MyWebServiceClient  wsClient){    
               this.wsClient = wsClient;
        }

        //Interface implentation
        //...
    }

Back to the question, whether you should add one more abstraction layer, I would say no because it's not necessary. Your example is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but the support of queries and criteria.

    @Repository
    public class DBRepository implements MyRepository{
        private EntityManager em;
        
        @Autowire
        public MyRepository (EntityManager em){    
             this.em = em;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class WebRepository implements MyRepository{
        private RestTemplate rt;
    
        @Autowire 
        public WebRepository (RestTemplate rt){    
             this.rt = rt;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class FileRepository implements MyRepository{
       
        private File file; 
        public FileRepository (File file){    
            this.file = file;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class WSRepository implements MyRepository{
       
        private MyWebServiceClient wsClient; 

        @Autowire
        public WSRepository (MyWebServiceClient  wsClient){    
               this.wsClient = wsClient;
        }

        //Interface implentation
        //...
    }

Back to the question, whether you should add one more abstraction layer, I would say no, because it's not necessary. Your example is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

added 285 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72

Right. This's the basic design by seggregationsegregation of concerns proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will lookslook often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories'srepositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here).

Repositories are an abstraction addressed to keep1 but the domain unaweresupport of the persistence implementationqueries and technical details. Their solely prupose is serving the domain as it need it. Unlike many developers think, repository interfaces can be totally different from each other.

In Spring Data JPA, the role DAO is played by the EntityManager. It manages the sessions, the access to the DataSource, mappings, etccriterias.

The Repository is already an abstraction in between services and datastoresdata stores. When we inherit fromextend Spring Data JPA repository interfaces, we are implementing this design implicitly. When we do this, we are paying a tax: a tight coupling with Spring's components. Additionally, we break LoD and YAGNI by inheriting several methods we might not need or wish not have. Not to mention that such an interface doesn't provide us with any valuable insight about the domain needs they serve.

IfThat said, extending Spring Data repository interfacesJPA repositories is too much coupling for you or you find that you don't need most of the methods inherited,not mandatory and you can make your ownavoid these tradeoffs by implementing a more plain and custom hierarchy of classes.

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private EntityManager em;
        
        @Autowire
        public MyRepository (@Autowire EntityManager em){
     
               this.em = em;
         }

        //Interface implentation
        //...
    }

Changing the datasourcedata source now just takes a new implementation which replacereplaces the EntityManager with a different datasourcedata source.

    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private RestTemplate rt;
    
        @Autowire 
        public MyRepository (@Autowire RestTemplate rt){
     
               this.rt = rt;
         }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private File file; 
        public MyRepository (File file){
     
               this.file = file;
         }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private MyWebServiceClient wsClient;  

        @Autowire
        public MyRepository (@Autowire MyWebServiceClient  wsClient){
     
               this.wsClient = wsClient;
         }

        //Interface implentation
        //...
    }

and so on.2

Back to the question, whether you should add one more abstraction layer, I would say no. It's because it's not necessary. Your example, IMO, is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

 

Finally, if you find Spring's repository interfaces not to be enough, if you need enhance Spring Data interfaces with new methods, Spring allows you to do so. Search a little bit about the BaseRepositoryFactoryBean implentation and @NoRepositoryBean annotation.1: Unlike many developers think, repository interfaces can be totally different from each other because each repository serves different domain needs. In Spring Data JPA, the role DAO is played by the EntityManager. It manages the sessions, the access to the DataSource, mappings, etc.

2: A similar solution is enhancing Spring's repository interfaces mixing them up with custom interfaces. For more info, look for BaseRepositoryFactoryBean and @NoRepositoryBean. However, I have found this approach cumbersome and confusing.

Right. This's the basic design by seggregation of concerns proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will looks often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories's interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here).

Repositories are an abstraction addressed to keep the domain unawere of the persistence implementation and technical details. Their solely prupose is serving the domain as it need it. Unlike many developers think, repository interfaces can be totally different from each other.

In Spring Data JPA, the role DAO is played by the EntityManager. It manages the sessions, the access to the DataSource, mappings, etc.

The Repository is already an abstraction in between services and datastores. When we inherit from Spring Data JPA repository interfaces, we are implementing this.

If extending Spring Data repository interfaces is too much coupling for you or you find that you don't need most of the methods inherited, you can make your own hierarchy of classes.

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private EntityManager em;
    
        public MyRepository (@Autowire EntityManager em){
     
               this.em = em;
         }

        //Interface implentation
        //...
    }

Changing the datasource now just takes a new implementation which replace the EntityManager with a different datasource.

    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private RestTemplate rt;
    
        public MyRepository (@Autowire RestTemplate rt){
     
               this.rt = rt;
         }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private File file; 
        public MyRepository (File file){
     
               this.file = file;
         }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private MyWebServiceClient wsClient; 
        public MyRepository (@Autowire MyWebServiceClient  wsClient){
     
               this.wsClient = wsClient;
         }

        //Interface implentation
        //...
    }

and so on.

Back to the question, whether you should add one more abstraction layer I would say no. It's not necessary. Your example, IMO, is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed.

Finally, if you find Spring's repository interfaces not to be enough, if you need enhance Spring Data interfaces with new methods, Spring allows you to do so. Search a little bit about the BaseRepositoryFactoryBean implentation and @NoRepositoryBean annotation.

Right. This's the basic design by segregation of concerns proposed by Spring Framework. So you are in the "Spring's right way".

Despite Repositories are frequently used as DAOs, the truth is that Spring developers took the notion of Repository from Eric Evans' DDD. Repository interfaces will look often very similar to DAOs because of the CRUD methods and because many developers strive to make repositories' interfaces so generics that, in the end, they have no difference with the EntityManager (the true DAO here)1 but the support of queries and criterias.

The Repository is already an abstraction in between services and data stores. When we extend Spring Data JPA repository interfaces, we are implementing this design implicitly. When we do this, we are paying a tax: a tight coupling with Spring's components. Additionally, we break LoD and YAGNI by inheriting several methods we might not need or wish not have. Not to mention that such an interface doesn't provide us with any valuable insight about the domain needs they serve.

That said, extending Spring Data JPA repositories is not mandatory and you can avoid these tradeoffs by implementing a more plain and custom hierarchy of classes.

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private EntityManager em;
        
        @Autowire
        public MyRepository (EntityManager em){    
             this.em = em;
        }

        //Interface implentation
        //...
    }

Changing the data source now just takes a new implementation which replaces the EntityManager with a different data source.

    //@RestController > @Service > @Repository >  RestTemplate

    @Repository
    public class MyRepositoryImpl implements MyRepository{
        private RestTemplate rt;
    
        @Autowire 
        public MyRepository (RestTemplate rt){    
             this.rt = rt;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  File

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private File file; 
        public MyRepository (File file){    
            this.file = file;
        }

        //Interface implentation
        //...
    }
    //@RestController > @Service > @Repository >  SoapWSClient

    @Repository
    public class MyRepositoryImpl implements MyRepository{
       
        private MyWebServiceClient wsClient;  

        @Autowire
        public MyRepository (MyWebServiceClient  wsClient){    
               this.wsClient = wsClient;
        }

        //Interface implentation
        //...
    }

and so on.2

Back to the question, whether you should add one more abstraction layer, I would say no because it's not necessary. Your example is only adding more complexity. The layer you propose is going to end up as a proxy between services and repositories or as a pseudo-service-repository layer when specific logic is needed and you don't where to place it.

 

1: Unlike many developers think, repository interfaces can be totally different from each other because each repository serves different domain needs. In Spring Data JPA, the role DAO is played by the EntityManager. It manages the sessions, the access to the DataSource, mappings, etc.

2: A similar solution is enhancing Spring's repository interfaces mixing them up with custom interfaces. For more info, look for BaseRepositoryFactoryBean and @NoRepositoryBean. However, I have found this approach cumbersome and confusing.

added 343 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading
added 1502 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading
added 197 characters in body; added 3 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading
added 446 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading
deleted 4 characters in body
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading
Source Link
Laiv
  • 15k
  • 2
  • 34
  • 72
Loading