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
Related
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.
I've looked through various documents and questions about it, but I haven't been able to find a clear answer.
I don't know how an interface that extends JpaRepository can be registered as a bean, and why it doesn't need the #Repository annotation.
In Spring, an interface cannot register a bean with that type without an implementation.
So I tried experimenting like JpaRepository myself, but it didn't work.
// JpaRepository
#NoRepositoryBean
public interface WackRepository {
}
// SimpleJpaRepository
#Repository
public class WackRepositoryImpl implements WackRepository {
}
public interface HelloRepository extends WackRepository {
}
#RestController
#RequiredArgsConstructor
public class HelloController {
private final HelloRepository helloRepository;
}
Parameter 0 of constructor in com.example.demo.HelloController required a bean of type 'com.example.demo.HelloRepository' that could not be found
HelloController, of course, has no implementation, so it is not registered as a bean and throws an exception.
Spring Data detects extensions of the Repository Interface.
In Spring Boot the interfaces extending Repository are found automatically without Spring Boot or if the interfaces are not below the SpringBootApplication in the package hierarchy you have to configure the packages:
#EnableJpaRepositories("com.acme.repositories")
Source: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.create-instances
I'm facing the following issue in a legacy code that I can't change. I have a multi module project which defines in the commons module a Spring Data interface as below:
package commons;
...
#NoRepositoryBean
public interface MyCustomRepository<P, I extends Number> extends JpaRepository<MyEntity, Integer>
{
MyEntity getOneAndCheck();
}
In another module I extend this interface as follows:
package data;
...
#Repository
public interface MyRepository extends MyCustomRepository<MyEntity, Integer>
{
...
}
So, the idea is that I don't want that Spring Data generates any implementation for the MyEntity getOneAndCheck() method 'cause it is implemented like this:
package data;
...
public class MyCustomRepositoryImpl implements MyCustomRepository
{
...
#Override
public MyEntity getOneAndCheck()
{
...
}
...
}
However, when I'm starting the application, I get the following exception:
...
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract MyEntity commons.MyCustomRepository.getOneAndCheck()! No property getOne found for type MyEntity!
...
So what it seems to happen is that Spring Data tries to generate a Query for the MyEntity getOneAndCheck() method, despite the #NoRepositoryBean annotation. This works as expected in the application I'm gonna migrate from Spring 3 with Spring Data to Spring Boot 2.5.
Not sure if the described behavior has anything to do with the fact that there are multiple Maven modules and that the repositories, the entities and the DTOs are in different modules. Not sure neither if there should be any difference between the way it runs currently with Spring and the one with Spring Boot. But the result is that all of the dozens of repositories in this legacy application are failing with the mentioned exception.
It might be important to mention that the main class needs to use annotations in order to tune the scanning:
#SpringBootApplication(scanBasePackages = "...")
#EnableJpaRepositories(basePackages={"...", "..."})
#EntityScan(basePackages= {"...", "..."})
public class MyApp
{
public static void main(String[] args)
{
SpringApplication.run(MyApp.class, args);
}
}
Not sure whether these annotations are supposed to change anything from the point of view of #NoRepositoryBean but the issue appeared as soon as I added this Spring Boot main class. It worked okay previously without Spring Boot.
Any suggestion please ?
Many thanks in advance.
Kind regards,
Seymour
There are two things that play together:
Spring Data's default custom implementation
Repository fragments
None of these apply because:
The default custom implementation follows the name of the actual repository. In your case, the implementation is named MyCustomRepositoryImpl whereas the repository name is MyRepository. Renaming the implementation to MyRepositoryImpl would address the issue
Since Spring Data 2.0, the repository detection considers interfaces defined at the repository level as fragment candidates where each interface can contribute a fragment implementation. While the implementation name follows the fragment interface name (MyCustomRepository -> MyCustomRepositoryImpl), only interfaces without #NoRepositoryBean are considered.
You have three options:
extracting your custom method into its own fragment interface and providing an implementation class that follows the fragment name:
interface MyCustomFragement {
MyEntity getOneAndCheck();
}
class MyCustomFragementImpl implements MyCustomFragement {
public MyEntity getOneAndCheck() {…}
}
public interface MyRepository extends MyCustomRepository<MyEntity, Integer>, MyCustomFragment {…}
Set the repositoryBaseClass via #EnableJpaRepositories(repositoryBaseClass = …) to a class that implements the custom method.
If you cannot change the existing code, you could implement a BeanPostProcessor to inspect and update the bean definition for the JpaRepositoryFactoryBean by updating repositoryFragments and adding the implementation yourself. This path is rather complex and requires the use of reflection since bean factory internals aren't exposed.
I'm working on a POC, using Spring Boot 2.0.5, Spring Data JPA using Hibernate. I'm trying to implement a way to stream the result sets for a custom criteria. I have seen examples like
public interface MyRepository implements JPARepository<Person,Long>{
#Query("select p from person p")
Stream<Person> findAll();
}
However I'm extending SimpleJPARepository and want to get results as a stream using a Criteria something like
Stream<Person> findAll(Criteria criteria);
Since I'm using class that extends SimpleJPARepository, I need to provide my implementation. But are there any methods in SimpleJPARepository or its parent classes, that can provide me default implementation using the criteria I provide. Any reference to such example is much helpful.
Also, in some examples I see that #NoRepositoryBean is used and in some cases #Repository. I'm confused between these two and which one should I use and why?
As per Spring Data JPA specifications Spring Data JPA, this is how you can create Criteria queries.
Step 1: extend your repository interface with the JpaSpecificationExecutor interface, as follows:
public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
…
}
Step 2: the findAll method returns all entities that match the specification, as shown in the following example:
List<T> findAll(Specification<T> spec);
Step 3: The Specification interface is defined as follows:
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
CriteriaBuilder builder);
}
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...