Spring data - Manual implementation - spring

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

Related

How to implement Spring Boot service classes without using impl and using a interface as dependency as DIP principle says?

I am trying to implement a Spring Boot REST API but I was asked to use a interface as dependency but no impl, and I don't know how to achieve this. The way I implemented was to have service classes for my entities and there I would just call the repository in my methods. I would like an example of implementation like this.
I watched some youtube tutorials but they all used impl classes
Your controller should have a field of your interface type, with the injecting annotation (in spring it's #Autowired). The DI framework will do the heavy-lifting on startup and inject the correct implementation at runtime
#Controller
public class MyController {
#Autowired
private MyInterface myInterface;
....
}
For this to work, your framework needs to recognize the concrete class. In spring you can achieve this in multiple ways - scanning package paths, xml configuration files and more.
Check the spring documentation to see which way suits you best

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.

Decorate spring boot repository

I'm working on a Spring Boot API that's supposed to be deployed later this month. We created our own interface for a repository, and extended the CrudRepository. Spring boot autowires everything.
What I would like to do is add more logging capabilities, such as LOGGER.info("searched for solution ID").
Currently our code looks like this:
#Repository
public interface ProductSolutionRepository extends CrudRepository<ProductSolution, String> {
public List<ProductSolution> findBySolutionId(#Param("solutionId") int solutionId);
Since Spring configures everything don't really see a way of decorating these functions to add logging functionality. Can someone help me out by pointing me to the documentation, showing a nice example, or explaining the concept behind logging decorators?
First, I would like to point out some redundant codes for you.
You don't need to annotate the repository with #Repository, spring boot can autowire it automatically.
#Param is used when you write a sql with #Query, you just need to declare your parameters here.
The repository is the dao layer. A normal practice, you should create a service for each repository and autowire the repository into the service. Then you can implement transaction or write logs there.
You can use a single file AOP Logging Aspect using AspectJ cutting across your repository interfaces layer and logging method name, input args and output.
Assuming for this purpose a RepositoryLoggingAspect class, you'd have to annotate it first with #Aspect:
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class RepositoryLoggingAspect {
//..
}
And then create a Pointcut aiming at your repository package you want to cut-accross:
#Pointcut("within(package.of.my.repositories..*)")
public void repositoriesPackagePointcut() {}
And finally define the logging logic in an #Around annotated method:
#Around("repositoriesPackagePointcut()")
public Object logMyRepos(ProceedingJoinPoint joinPoint) throws Throwable {
//log method name using: joinPoint.getSignature().getName()
//log method arguments using: Arrays.toString(joinPoint.getArgs())
//store and log method output using: Object myResult = joinPoint.proceed();
}

How to hide spring data repository functions in service class?

I am using spring data JPA repository, my requirement is when i call repository class methods in service class it should show only custom methods like addUser(X,Y) instead of save().
Few things i understand, implementation of spring repository is provided by spring framework at runtime, So we cannot provide out own implementation. (This will overhead).
All methods in JPARepository is public only, so its obivious when we implement this interface all methods will be visible through out.
I am thinking of using DAO and Repository both at same time. DAO will provide custom function signature and repository will implement DAO interface.
Any Hack ?
If you don't want the methods from JpaRepository or CrudRepository, don't extend those but just Repository instead. It is perfectly fine to have a repository interface like
MyVeryLimitedRepository extends Repository<User, Long> {
User findByName(String name);
}
Of course methods like addUser(X,Y) will need a custom implementation.
You can very well use DAO pattern in this case .
By implementing DAO Pattern in Service Class
You create a wrapper between Service and Repository.
You can custom code your DAO layer to only expose custom methods to service layer

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