Multitenancy with Micronaut for JDBC without Hibernate/JPA or GORM - multi-tenant

Im working with Micronaut and Im trying to implement the Multitenancy feature for my app. My goal is to implement it with java in DATABASE mode for many oracle DBs, however all the info I found is related to spring, hibernate/jpa or gorm and I don't want/can't use any of those.... is it possible to achieve this? How can I do it?
Thanks in advance.

You can implement multitenancy using the repository per database technic:
interface PersonRepository extends CrudRepository<Person, Long> {
}
#JdbcRepository(dataSource = "db1", dialect = Dialect.ORACLE)
interface Db1PersonRepository extends PersonRepository {
}
#JdbcRepository(dataSource = "db2", dialect = Dialect.ORACLE)
interface Db2PersonRepository extends PersonRepository {
}
Or the second option (only available starting from Micronaut Data 3.5.0) is to specify the database on the inject point:
#JdbcRepository(dialect = Dialect.ORACLE)
interface PersonRepository extends CrudRepository<Person, Long> {
}
#Singleton
class MyService {
#Inject
#Repository("db1")
PersonRepository db1PersonRepository
#Inject
#Repository("db2")
PersonRepository db2PersonRepository
}
In the future, it should be possible to have GORM-style multitenancy.

Related

SpringBoot unit test using JPA and JOOQ

I had to start with the following codebase: an ordinary JpaRepository that also implemented more complex custom JPQL queries defined inside TokenOrderRepositoryCustom
public interface TokenOrderRepository<T extends TokenOrderEntity> extends
JpaRepository<T, Long>,
TokenOrderRepositoryCustom {
}
This was unit tested using the following configuration:
#DataJpaTest
#AutoConfigureTestDatabase (replace = AutoConfigureTestDatabase.Replace.NONE)
public class TokenOrderRepositoryTest {
}
Now, I had to add a complex query in TokenOrderRepository that uses window functions and I've settled to use JOOQ for that. In order to do that I had to use JOOQ's DSLContext in TokenOrderRepositoryCustomImpl
public class TokenOrderRepositoryCustomImpl implements TokenOrderRepositoryCustom {
#Autowired
private DSLContext jooqContext;
}
The problem is that now I have a mixed repository that uses both JPA and JOOQ and I cannot figure how to modify the configuration for TokenOrderRepositoryTest to accommodate that.
Your guidance would be much appreciated. Thanks!
I finally got around this problem by importing the configuration defining the DSLContext for the JPA tests. I don't know if it is the perfect approach, but it works effortlessly.
#DataJpaTest
#AutoConfigureTestDatabase (replace = AutoConfigureTestDatabase.Replace.NONE)
#Import(value = JOOQConfiguration.class)
public class TokenOrderRepositoryTest {
}

Spring JPA: Parameter 0 of constructor in ... required a bean of type ... that could not be found

I do a simple web app but on start I get that error. I'm using Spring JPA. The message's about Spring could not find any bean to do autowired. But if I use CrudRepository I always have standard repository implementation. I can't get why Spring can't find own bean? What do I do wrong?
Service layer
#Controller
#RequestMapping("/api/v1/get")
public class UserService {
private final UserRepository repository;
#Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
Add annotation #Repository - it will allow Spring to discover this repository during Component Scan
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
I get it: I forgot to add default constructor for my model class. And if I use this class in Spring jpa CrudRepository<User, Long> it has to be with some default constructor.

Can we use CrudRepository and ReactiveCrudRepository simaultaneously in the application

I am using couchbase in my springboot application and using both ReactiveCrudRepository and CrudRepository separately. But while using CrudRepository method it is throwing me the following error
"reactor.core.publisher.MonoOnAssembly cannot be cast to my POJO
You can use it in the same project but they have to be different classes and implement different interfaces.
Synchronous Repository:
public interface UserEntityRepository extends
CouchbasePagingAndSortingRepository<UserEntity, String> {
}
Async Repository:
public interface ReactiveUserEventRepository extends
ReactiveCouchbaseSortingRepository<UserEventEntity, String> {
}
There is a big tutorial talking about it here: https://docs.couchbase.com/tutorials/profile-store/java.html#storing-user-events

How Spring creates an implementation of CrudRepository interface+CustomRepositoryInterface?

Hy,
I have the next code in Spring
#Repository
public interface UserRepository extends CrudRepository<User, String>,
UserRepositoryExtension<RosterUser> {
...any custom spring JPA methods...
}
Extension Interface:
public interface UserRepositoryExtension <T> {
public T put(T entity);
}
Implementation of Extension interface
public class UserRepositoryExtensionImpl implements
UserRepositoryExtension<User> {
#Autowired
EntityManager entityManager;
#Override
public User put(User user) {
entityManager.....(any logic here)
}...
}
I knew that Spring was able to create an inplementation of the UserRepository+CrudRepository interface methods in inyection time but what I dont get is:
how spring creates these implementations and combine them with my implementation of UserRepositoryExtensionImpl(what happens under the hood?)
How Spring knows what entityManager to use in the implementation class of UserRepository+CrudRepository it creates in injection time? It takes the entityManager from the context or from the class UserRepositoryExtensionImpl where an entityManager is declared?
Thanks

How to access entity manager with spring boot and spring data

How can I get access to the Entity Manager in the repository when using Spring Boot and Spring Data?
Otherwise, I will need to put my big query in an annotation. I would prefer to have something more clear than a long text.
You would define a CustomRepository to handle such scenarios. Consider you have CustomerRepository which extends the default spring data JPA interface JPARepository<Customer,Long>
Create a new interface CustomCustomerRepository with a custom method signature.
public interface CustomCustomerRepository {
public void customMethod();
}
Extend CustomerRepository interface using CustomCustomerRepository
public interface CustomerRepository extends JpaRepository<Customer, Long>, CustomCustomerRepository{
}
Create an implementation class named CustomerRepositoryImpl which implements CustomerRepository. Here you can inject the EntityManager using the #PersistentContext. Naming conventions matter here.
public class CustomCustomerRepositoryImpl implements CustomCustomerRepository {
#PersistenceContext
private EntityManager em;
#Override
public void customMethod() {
}
}
In case you have many repositories to deal with, and your need in EntityManager is not specific for any particular repository, it is possible to implement various EntityManager functionality in a single helper class, maybe something like that:
#Service
public class RepositoryHelper {
#PersistenceContext
private EntityManager em;
#Transactional
public <E, R> R refreshAndUse(
E entity,
Function<E, R> usageFunction) {
em.refresh(entity);
return usageFunction.apply(entity);
}
}
The refreshAndUse method here is a sample method to consume a detached entity instance, perform a refresh for it and return a result of a custom function to be applied to the refreshed entity in a declarative transaction context. And you can add other methods too, including query ones...

Resources