How Spring creates an implementation of CrudRepository interface+CustomRepositoryInterface? - spring

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

Related

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.

How to autowire SimpleJpaRepository in a spring boot application?

I'm working on a project that uses SpringBoot 2.0.5 version, Spring Data JPA to persists and retrieve records using JPA. I autowired SimpleJpaRepository in the service layer. But while starting my application, it failed with
"NoSuchBeanDefinitionException"- No qualifying bean of type
'org.springframework.data.jpa.repository.support.SimpleJpaRepository<?, ?>'
available: expected at least 1 bean which qualifies as autowire candidate.
My controller, service and DAO are like below
Controller class:
#Controller
public class MyController{
#Autowired
private MyService<Person,PersonPK> service;
Service layer as
public interface MyService<V,K>{
methods defined
}
#Service("service")
public class MyServiceImpl<V,K> implements MyService<V,K>{
#Autowired
private SimpleJpaRepository<V,K> repository; // This dependency is failing
}
Application as :
#SpringBootApplication (exclude = {SecurityAutoConfiguration.class})
#EnableJpaRepositories
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Is my approach incorrect? Is that not the correct way of autowiring the SimpleJpaRepository.
There is no need for me to extend SimpleJpaRepository as Spring provided JPARepository is good for me, for now.
Thanks
You still need to create a repository interface that extends JpaRepisitory, or the spring repository type of your choice.
To quote the spring data documentation:
1.2.1 Defining repository interfaces
As a first step you define a domain class-specific repository interface. The interface must extend
Repository and be typed to the domain class and an ID type. If you
want to expose CRUD methods for that domain type, extend
CrudRepository instead of Repository.
Once you do create a new repository type, you will autowire by that type rather than the SimpleJpaRepository.
One way to get an implementation of the SimpleJpaRepository is by using a Configuration class to create an instance as a bean that you will use inside your service.
#Configuration
public class PersistanceConfiguration {
#PersistenceContext
private EntityManager entityManager;
#Bean
public SimpleJpaRepository<YourEntity, Long> getYourEntitySimpleRepository() {
return new SimpleJpaRepository<>(YourEntity.class, entityManager);
}
}
And inject it to your service as you would do with a JpaRepository, for example:
#Service
public class YourEntityServiceImpl<YourEntity, Long> implements YourEntityService {
private JpaRepository<YourEntity, K> repository;
private SimpleJpaRepository<YourEntity, K> simpleRepository;
#Autowired
public YourEntityServiceImpl(YourEntityRepository repository, SimpleJpaRepository<YourEntity, Long> simpleRepository) {
this.repository = repository;
this.simpleRepository = simpleRepository;
}
}
You should create a repository interface that extending JpaRepisitory.
#Repository
public interface MyRepository extends JpaRepisitory<T, ID> {
//
}
And the you should Autowired in your service class.
#Service("service")
public class MyServiceImpl<V,K> implements MyService<V,K>{
#Autowired
private MyRepository myRepository;
}

How to access Entity Manager within a service in spring boot project?

I've googled so many times for how to access entity manager in spring boot, and did what posts said, but it didn't work. I want to access Entity Manager so that i can do some custom query operation. Here i defined the custom interface in a dependent package named 'customrepository':
public interface PostRepositoryCustom {
void refresh(Post post);
}
Then I implemented this interface in another package named 'customrepositoryimpl':
public class CustomPostRepositoryImpl implements PostRepositoryCustom {
#PersistenceContext
private EntityManager em;
#Override
public void refresh(Post post) {
em.refresh(post);
}
}
Finally, I defined a standard repository interface which extends 'CrudRepository' and the custom repository:
public interface PostRepository extends CrudRepository<Post,Long>,PostRepositoryCustom {}
Every steps i followed What i googled and Official Documents, BUT when i run my application, i get this:
Error creating bean with name 'postRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract void com.example.demo.customrepository.PostRepositoryCustom.refresh(com.example.demo.model.Post)! No property refresh found for type Post!
Why? Anyone tell me where should i correct my mistakes?
Spring cannot locate the beans, so try annotate with #Repository
#Repository
public class CustomPostRepositoryImpl implements PostRepositoryCustom {
#PersistenceContext
private EntityManager em;
#Override
public void refresh(Post post) {
em.refresh(post);
}
}
and
#Repository
public interface PostRepository extends CrudRepository<Post,Long>{
}

Spring Data JPA custom method causing PropertyReferenceException

I have been trying to create a spring boot application. In my application I would like to add some custom methods to save the data instead of using the default save method.
My application entry point is something like this:
#Configuration
#ComponentScan
#EnableJpaRepositories(repositoryImplementationPostfix = "CustomImpl")
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
#PropertySource("application.properties")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I have changed this line repositoryImplementationPostfix to even Impl but, it didn't work.
My CrudRepository
#RepositoryRestResource
public interface TaRepository extends CrudRepository<Ta, Integer> ,TestRepository{
List<Ta> findByName(#Param("name") String name);
}
My Custom Repository:
public interface TestRepository {
public void myCustomMethod(TestDto dto);
}
My Custom Repository Impl
public class TestRepositoryCustomImpl implements TestRepository{
#PersistenceContext
private EntityManager em;
#Override
public void myCustomMethod(TestDto model){
}
NOTE:
If I change my CrudRepostory from the mentioned to this:
#RepositoryRestResource
public interface TaRepository extends CrudRepository<Ta, Integer> {
List<Ta> findByName(#Param("name") String name);
}
everything works fine. But not with the custom method implementation.
For Spring Data JPA #Repository or #RepositoryRestResource you never need to implement a Custom Interface. For any simple query you can create any kind of method, please follow the simple guide.
http://docs.spring.io/spring-data/jpa/docs/1.4.1.RELEASE/reference/html/jpa.repositories.html
For a complex query you can use JpaSpecificationExecutor.
How can I create a Predicate from a HQL query?

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