Using CustomRepository implemention with spring boot & spring-data-jpa - spring

Background
I'm trying to create a custom implementation for my spring boot data jpa application.
I've created a UserRepsitoryCustom interface with "List<User> getUsers(String type)" method.
I've created a UserRepository interface with extends CrudRepository<User, Long>, QueryDslPredicateExecutor<User>, UserRepositoryCustom.
I've created a UserRepositoryImpl class which extends UserRepositoryCustom interface and implements the "getUsers(String type)" method.
Problem
My expectation was that spring boot-data-jpa will create me a repository bean that combines all the goodies from CrudRepository & QueryDslPredicateExecutor and additional will know to use my custom implementation repository.
Currently, all I'm getting is
PropertyReferenceException: No property getUsers found...
I haven't annotated the UserRepositoryImpl with any #Component or #Repository. and I haven't changed any default configuration.
What am I doing wrong?
Thanks!

I've found my problem!!! The UserRepositoryImpl was in the wrong package name... I've moved it to the right package name and it's done!

Related

Can I| use #Repository for DAO layer in spring boot

Can we use #Repository for DAO layer in spring boot ?
What is the difference between #Component and #Repository ?
Which one should we use for DAO layer in Spring boot ?
#Repository is a specialization of #Component whose purpose is to handle DAO. So the answer is yes.
#Repository javadoc states :
Indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects".
Teams implementing traditional Java EE patterns such as "Data Access Object" may also apply this stereotype to DAO classes, though care should be taken to understand the distinction between Data Access Object and DDD-style repositories before doing so. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use as appropriate.
#Repository is an annotation marker. No difference between #Component and #Repository, spring already can create bean instance from your interface if you extends JpaRepository or other spring repository interfaces
For example:
public interface UserRepository extends JpaRepository<User, BigInteger> {
User findByUsernameOrEmail(String username, String email);
}
For more information please follow the link

Should I annotate Spring Data Repositories with #Repository [duplicate]

I'm using Spring Data JPA repositories (like MyRepo extends JpaRepository) and it works without #Repository and without #EnableJpaRepositories annotations. Could someone explain why?
Probably you are using Spring Boot.
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you use auto-configuration, repositories are searched from the package containing your main configuration class (the one annotated with #EnableAutoConfiguration or #SpringBootApplication) down.
Please check the Spring Boot Reference Documentation (v2.7.2) for more details.
you don't need #Repository to make use of Spring Data JPA.
The Interface extending the CrudRepository or JPARepository would work even without annotating it with #Repository.
The Core reason why you need to have this annotation in place is it makes unchecked exceptions thrown in the DAO layer eligible to be translated into Spring DataAccessException. Which in turn would be easier to work with. This is the important aspect of using #Repository
More details see this -> https://www.youtube.com/watch?v=z2re1MfWtz0&list=PLO0KWyajXMh4fGMvAw1yQ1x7mWayRcmX3&index=8&t=0s
For more information look into these class which is used to auto-configure Spring Data JPA Repositories:
JpaRepositoriesAutoConfigureRegistrar
Docs : http://www.atetric.com/atetric/javadoc/org.springframework.boot/spring-boot-autoconfigure/1.2.0.RELEASE/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfigureRegistrar.html
#EnableJpaRepositories
private static class EnableJpaRepositoriesConfiguration {
}

#Repository in Spring 4

#Repository
public interface userRepository extends JpaRepository<User, Long> {
}
There are many sites showing this way of creating DAO in Spring 4 using JpaRepository. #Repository also creating instance just like #Component, #Service etc. Container internally beans by using new operator while component scan (using #Component scan annotation) of classes having annotation #Component, #Service etc. Then how container create instance for #Repository as shown above, as it is an interface which is purely abstract and we can't create instance for interface using new operator.
Spring will create a SimpleJpaRepository instance for declared Interfaces that extend JpaRepository.
Note: there is much more magic going on. You can add your own queries via #Query to the interface and Repositories also support transaction management. To achieve that the Repository will be wrapped in a proxy which can intercept and dynamically implement its methods.

Spring Boot NoUniqueBeanDefinitionException

I am converting a Java EE project to Spring Boot 1.1.9. Before converting, I was used to CDI 1.2 for Dependency Injection.
I have an interface :
public interface AdminManager<V extends AdminView>
I also have a few implementations of this interface. They look like this :
#Repository
#Transactional(propagation=Propagation.REQUIRED)
public class DBRuleManager implements AdminManager<AdminRuleView>
#Repository
#Transactional(propagation=Propagation.REQUIRED)
public class DBFlagLogicManager implements AdminManager<AdminFlagLogicView>
Now, I have coded a REST endpoint, that is supposed to use the DBRuleManager:
#Controller
#RequestMapping("/admin/rule")
public class RestAdminRule {
#Inject
private AdminManager<AdminRuleView> manager;
}
When I run mvn spring-boot:run I get the following NoUniqueBeanDefinitionException :
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.company.server.admin.AdminManager] is defined: expected single matching but found 2: DBRuleManager,DBFlagLogicManager
I've read that Spring 4 is supposed to manage this kind of situation. What's the problem then? This was working well using CDI.
When trying to solve another problem (about proxies for #Transactional implementations), I found a way to get rid of this issue.
I used this parameter :
#EnableTransactionManagement(proxyTargetClass=true)
And then I was able to inject my AdminManager<AdminRuleView> directly. I don't understand why, though...

Spring data - Manual implementation

Is it possible to write my own function implementation along usage of spring repositories?
I would like to actually implement the function
getUserByFirstName()
and not get it automagically.
While i still want to get
getUserById()
automagically from spring-data.
1) is it possible?
2) is it possible to achieve logging for all methods spring data automagically generates? (or should i write them manually with
logger.log("entering method ...");
See section 1.3 of the manual for the first requirement:
http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.single-repository-behaviour
For the second requirement I guess some AOP based solution might work for you well here. See here for example using Spring's AOP support:
logging with AOP in spring?
Yes, you can!!!
There is an amazing feature in Spring data that allows this:
Create an interface with your custom method:
public interface UserRepositoryCustom {
User getUserByFirstName();
}
Make your Spring Data interface extends this new interface, as well as the Spring data crud interface (or JPA, Mongo or whatever spring data interface you're extending):
public interface MySpringDataRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
}
Create a class that implements only your custom interface. The name of the class must be Impl, for instance: UserRepositoryImpl:
public class MySpringDataRepositoryImpl implements UserRepositoryCustom {
public User getUserByFirstName(){
//Your custom implementation
}
}
Now, you only need to inject the Spring data repository in your service and you can use both methods: the spring-data implemented method and your custom implemented method:
#Inject private MySpringDataRepository myRepository;
That's it!!
Look at this section in the documentation:
Spring Data Custom implementations

Resources