Some of the examples on internet use #Transactional annotation on DAO implementation methods while some use this annotation for the service layer methods. Where is it more appropriate to put the #Transactional and why?
Similarly where to put #Repository annotation. On the DAO interface or on the DAO implementation?
I have always used #Service and #Repository annotations on their implementations, but they can be put in either one. Although, putting it on a interface would mean that you won't be able to have more than one implementation, because you would get a NoUniqueBeanDefinitionException error.
In the case of #Transactional, it depends, but normally it goes on the service. If you want to be able to add various DB calls on one transaction, then it should go in the service. If you want to make small transactions, then on the DAO would be best, but then, you wouldn't be able to modify several tables in one single transaction. Another con of having it on the DAO, is that you won't be able to rollback multiple modifications, only the ones that are bing executed by the DAO.
EDIT
After several projects using Spring, each one of different proportions, I end up changing my own practices. I would like to add that even though adding #Transactional to the service layer isn't exactly bad practice, it can be negatively affect the performance of the application. So in my own experience, it is better to add it to the DAO/Repository layers and only add at function level in the service layer, if a transaction must be atomic.
One more thing, if you are using Spring Data, the #Repository must be added on the interface. Only if you extend the JpaRepository will you need to add the #Repository annotation on the implementation. In this case, the interface of the JpaRepository and the custom implementation will both have #Repository.
Related
I am implementing some of my business logic in my facade layer (which does some calculations and makes calls to service layers etc). What is the recommended stereotype for this layer, similar to #Service on service layer ? I use #Component as of now. Is it worth creating a new annotation as I'm using the same pattern across multiple projects?
It depends on whether you need to implement some logic on all the facade methods. For example , suppose you need to apply an AOP aspect on all the facade methods , by making a new specific annotation for it , you can locate the correct facade methods and process them based on the presence of this new annotation rather than a hard-coded list.
The documentation also mentions it:
Therefore, you can annotate your component classes with #Component,
but, by annotating them with #Repository, #Service, or #Controller
instead, your classes are more properly suited for processing by tools
or associating with aspects. For example, these stereotype annotations
make ideal targets for pointcuts. #Repository, #Service, and
#Controller can also carry additional semantics in future releases of
the Spring Framework. Thus, if you are choosing between using
#Component or #Service for your service layer, #Service is clearly the
better choice. Similarly, as stated earlier, #Repository is already
supported as a marker for automatic exception translation in your
persistence layer.
Here as Spring needs to locate all repository classes to apply an automatic exception translation for them , so it creates a new specific annotation #Repository.
My application is based on Spring Boot, Hibernate, MySQL using Spring Data JPA to stitch them.
Use case is to use slave db node for doing heavy read operations so as to avoid all traffic being served from master mysql node. One way of achieving this is to have multiple Entity Managers pointing to separate data sources(one to master and other to slave node). This way has been explained quite well in below SO questions and blogs.
Spring Boot, Spring Data JPA with multiple DataSources
https://scattercode.co.uk/2016/01/05/multiple-databases-with-spring-boot-and-spring-data-jpa/
Where I am stuck is to understand if there is a way I can inject different entity managers for different use cases in my Repository Annotated Interface.
The only way I see it can be done is extending repository with a custom implementation which gives uses custom entity manager annotated with relevant persistenceContext like below.
public interface CustomerRepository extends JpaRepository<Customer, Integer>, MyCustomCustomerRepository{
}
public class MyCustomCustomerRepositoryImpl implements MyCustomCustomerRepository {
#PersistenceContext(unitName = "entityManagerFactoryTwo")
EntityManager entityManager;
}
I would like to avoid doing this custom implementation. Any help around solving this use case(which I feel should be very common) would be appreciated.
NOTE: Entities are same in both databases so giving separate packages for entity scanning and similar solutions might not work.
Here is a nice sample you can use:
dynamic-datasource-routing-with-spring.
Inside you can find an AbstractRoutingDatasource + an interceptor for a custom annotation that wires the service method to a required database.
However you can just use datasource switch explicitly.
Below is the pull request that shows the diff and how I made it work with most configurations annotation driven instead of xml. It is based on cra6's answer above. i.e. using spring's RoutingDataSource capability.
https://github.com/himanshuvirmani/rest-webservice-sample/pull/1/files
The moment I include the #Transactional annotation on a #RequestMapping, I notice in springboot that the url mappings do not auto-configure.
What could be responsible for this?
I want a case where (C)R(UD) rest calls work within a transaction.
If you're goal is to ensure your CRUD operations happen within a transaction, then using Spring Data JPA, this is done for you by default. Creating a repository interface that extends CrudRepository for example, your query methods will inherently be #Transactional. You can customize the #Transactional attributes by manually annotating a query method on your repository, but this need only be done if you want non default behaviour.
See the Spring Data JPA docs for more details.
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
Taking an example: I want some entities to be persisted in MongoDB and some in Cassandra.
I have my repository interfaces extending CrudRepository. My Cassandra entities have #Table and my MongoDb entities have #Document annotations.
However, on startup, spring-data attempts to create an instance of a MyMongoObjectRepository, and thus complains that "Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation".
How are the libraries discovering which repository interfaces they are supposed to implement, and how can I control them so they don't try to implement them for unsupported entities?
Further question: if I wanted to store some entities in both storage systems, can multiple implementations of a single repository be generated, or do I need an interface for each store?
Edit
On further inspection, the problem seems to be from the entity scanning rather than the repository scanning. Both mappers pick up all the entities (as their annotations all extend #Persistent). One of the Mongo entities has a nested entity (without any annotations) that the Cassandra mapper cannot deal with.
You can use a basePackages setting in #EnableMongoRepositories and #EnableJpaRepositories to specify where they should look for repository definitions.
Like so:
#EnableMongoRepositories(basePackages={
"com.some.package.to.look.inside",
"com.some.package.to.look.also.at"
})
And
#EnableJpaRepositories(basePackages={
"com.some.differentpackage.to.look.inside",
"com.some.differentpackage.to.look.also.at"
})
For this to work you need to namespace your repository definitions in sensible packages.
Answer to your follow up question:
If you wanted to store entities multiple places at once I would implement a service in front of the repositories making use of #Autowire to dependency inject the repositories and setting a #Transactional on the service method which calls repository methods. Having #Transactional on the service method ensures that if an error would occur while saving it will ensure that no half-way saves are left laying around, even doing rollbacks if necessary.
Edit:
#Transactional does not work for db's that do not support transactions like Cassandra and MongoDB.
Problem is that all the different entity scanners use #Persistent as an annotation they're looking for, while all the repo-specific annotations (#Table, #Document, etc.) also have #Persistent as a meta-annotation.
Therefore, the entities for the different repositories must be in separate packages, and you must construct your own scanner in order to pass the packages to it, as it doesn't not accept a generic filter.
I'm using the #Transactional annotation for my entire Dao class with spring and hibernate. Everything works great, it's just that I would like to omit the behaviour for a few non database related methods in my Dao.
http://static.springsource.org/spring/docs/2.5.4/reference/transaction.html#transaction-declarative-annotations
Every time I step into these methods during a debugging session, I always get to JdkDynamicAopProxy.class which is super annoying.
Is there any way to omit transactional for specific methods? Or at least fix this annoying debugging behavior?
In Spring you can put the #Transactional annotation on only the methods you want to make transactional, instead of putting it at the class level.
Otherwise perhaps consider extracting those specific non-transactional methods into a separate class?