Adding new DB support in spring data - spring-boot

Currently spring data has multiple db support (mysql, cassandra, mongo.. very big list), however i want to add my custom repository from the scratch like adding custom db support in spring data. I don't want to extend any existing repositories, instead I want to create a parallel repository strutcutre for my custom datasource. Looking at current implementation it looks like tedious task. It would be a great if someone could help me with minimal requirement to do this.

You could create a repository annotated bean where you would inject EntityManager or the proper bean that is acting like that, depending on database type that you are using.
#Repository
public class MyCustomRepositoryImpl implements MyCustomRepository {
#Autowired
private EntityManager entityManager;
//the methods that you are going to create.
}
For more details see:
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
Chapter: 1.3 Custom implementations for Spring Data repositories

Related

How to use multiple JPA implementations in a Spring Boot project?

Is it possible to use multiple JPA implementations in a Spring Boot project ? For example Hibernate for one data source/database and Eclipse Link for another data source/database. If it is possible then how can we use it.
Using Hibernate I successfully handle multiple data source in a single spring boot project. But I don't know how to use multiple JPA in a project .
Yes It is possible you can implements as many times you want jpa interface
You need to create different repository for each entity and implements the JpaInterface in each repository
for example-:
#Repository
public interface CommentRepository extends JpaRepository<Comment,Long> {
}
NOw to use with different class just replace
1- Comment as that class Name
2- and Long as that class id datatype

spring-data-jdbc integrate with mybatis

I am currently using myBatis for my project, it is good for complex SQL, but I found that I need to create many redundant SQL for basic CRUD. So I come across spring-data-jdbc (here), which is a very nice library (similar to spring-data-jpa but without JPA persistence) to help to generate CRUD SQL statement via method name.
The guide on their official website on how to integrate with myBatis is very vague, I couldn't find any other source which showing how to do that. Basically I am looking for a way to do like below:
#Repository
#Mapper
public interface PersonRepository extends CrudRepository<Person, Long> {
//via spring-data-jdbc
List<Person> findAll();
//via spring-data-jdbc
List<Person> findByFirstName(String name);
//via myBatis, the actual query is in PersonMapper.xml
List<Person> selectAllRow();
}
As you can see, when I call findAll and findByFirstName, they will be handled by spring-data-jdbc. When I call selectAllRow, it will look for corresponding myBatis mapper file for actual SQL. In this way I can combine two mechanism to handle simple CRUD query and complex query (via myBatis) together.
But above doesn't work, so currently I have to split them into two interface, one for PersonRepository, and another one for PersonMapper, which is not a very nice design.
Anyone has done similar before?
Having two separate interfaces one for repository and another for mybatis mapper is just how mybatis integration in spring-data-jdbc works as of now (version 2.2.1).
Mapper is just an implemenation detail of the spring data repository and just should not be used by the clients, so it should not be an issue.
What you want can be probably done but will require quite some work and might not be worth it.
#Repository annotation instructs spring-data-jdbc to create a proxy implementing PersonRepository with all the machinery of fetching/saving objects to the database.
#Mapper on the other hand instructs mybatis-spring to create another proxy that will handle queries from the mapping provided in xml or via annotations on the interface method.
Only one of this proxies can be injected in the places where you are going to use PersonRepository. What you can do is to create your own proxy for PersonRepository that will create both spring-data-jdbc and mybatis proxy and will dispatch calls to them. But the complexity of this solution will be rather high compared to a simple class that delegates to two separate PersonRepository and PersonMapper.
Update: it seems there is a way to combine mybatis mapper with repository as described in this comment https://github.com/spring-projects/spring-data-jdbc/pull/152#issuecomment-660151636
This approach uses repository fragments to add mybatis fragment to the repository implementation.

where does jpa picks up the method userbyusername as i have not given any implementation and i have checked the inner classes too

In my spring boot project, I am using this starter jpa . i have done all the db related thing in appliction.properties. Project is working fine . I fail to undestand where is this methods defination. We have just defined a abstract method how is this method even working?
public interface UserRepository extends JpaRepository<UserEntity, Integer>{
Optional<UserEntity> getUserByUserName(String user);
}
This is part of the magic of JPA Repositories. I don't actually know the details of how it works either, I just know how to use it.
Ultimately, I think it has to do with how Spring proxies interfaces. Spring will create an instance of an interface at runtime. When the methods are named according to the specs, Spring can generate an appropriate method.
Here is a good article that goes into detail on how you can construct the method names to make the query that you want: https://www.baeldung.com/spring-data-derived-queries.

Multiple datasources in Spring Boot Repository Annotated Interface

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

spring data like functionality for JEE6

I have experience building applications on the Spring Framework primarily. I was wondering if there was anything similar to the Spring Data API (to support a Data Access Layer) in the JEE6 space?
I know I can wire in an entity manager like:
#PersistenceContext
EntityManager em;
Ideally I would like to avoid writing reams of boiler plate JPA code on Data Access beans, is an API similar to SpringJPA which can help cut down on the amount of boilerplate code such as findAll(), findByX() etc. For example, with SpringJPA I can define a bean as:
#Repository
public interface FooRepository
extends JpaRepository<Foo, String>
{
}
Whereas in vanilla JEE6 I would need a
a FooRepository interface with methods Foo findOne(Long), List<Foo> findAll()
a FooRepositoryImpl which implements the interface and interacts with the EntityManager
Spring Data JPA ships with a CDI extension to simply #Inject a repository into your CDI managed bean. See the reference documentation for details. The approach still requires Spring JARs on the classpath but no container being bootstrapped. This functionality is also available for MongoDB repositories.

Resources