what is the use of CrudRepository in springboot - spring

#RepositoryRestResource
public interface StudentRepository extends CrudRepository<Student, Long>
{
public List<Student> findById(long id);
//#Query("select s from Student s where s.age <= ?")
public List<Student> findByAgeLessThanEqual (long age);
}
what does <Student, long> mean in the CrudRepository<Student, long> and what are the various parameters that can be passed to cruderepository.

The main idea of CrudRepository is to give you opportunity to use main operations with data without creating your own implementation. You just create needed methods and for most simple cases Spring will create implementation for you (if you use right naming convention for your methods).
First parameter (Student in your case) is a type of entity with which current Repository is working, second parameter (Long in your case) is a type of Id in this entity.

CrudRepository provides methods for the CRUD operations. This interface extends the Repository interface. If you are extending the CrudRepository, there is no need for implementing your own methods.
If do not want data from custom parameter, you have to write custom query for it.
you can use only that parameters which is their in your CrudRepository.

Related

Dynamic JPA Projections with extended interface and generics

I am looking to use Spring JPA Dynamic Projections to limit the number of fields returned from queries. The table I'm using is wide, but the projection still contains around 10 fields. Therefore I am trying to use Dynamic Projections. The problem seems to be with trying to specify the methods in the repository interface since I first have an interface that extends the JpaRepository using an abstract class and then I have an interface the extends that one using the actual class.
I have tried various approaches to limiting the number of fields and this one seems to be the closest to what I want to use.
Here is my repository on the abstract class User:
#NoRepositoryBean
public interface UserRepository <T extends User> extends JpaRepository<T,
Long>{
<S extends T> S findByLoginName(String loginName);
}
Here is my actual repository on the actual class ConcreteUser:
#Repository
public interface ConcreteUserRepository extends UserRepository<ConcreteUser> {
}
In my service class implementation I have a method call that looks like this:
ConcreteUser user = this.userRepository.findByLoginName(loginName);
This of course returns a large number of fields, so I created an interface that contains the subset of fields that I want called UserProfile. The field names are exactly the same as those in the ConcreteUser. I then added 'implements UserProfile' to the User class. I don't know if that is necessary, but I'm trying to get the generics working so that I can do something like this:
#NoRepositoryBean
public interface UserRepository <T extends User> extends JpaRepository<T,
Long>{
<S extends T> S findByLoginName(String loginName, Class<S> clazz);
}
and then call it like this:
ConcreteUser user = this.userRepository.findByLoginName(loginName, ConcreteUser.class);
UserProfile profile = this.userRepository.findByLoginName(loginName, UserProfile.class;
I've tried various approaches with the generics. I've also tried using my DTO class UserProfileDTO instead of the UserProfile interface.
I am having problems with getting the Generics correct because of the extra level of abstraction.

Writing generic spring jpa repository for all entities

I am working on Spring Boot application.
We have Service Layer,Rest Controller and Dao as repository.
I have 20 to 30 tables in my database and I dont want to create repository for each entity and extends that to CrudRepository.
ex : User is an Entity, to perform persistance operations on User, I have to create UserRepository which extends CrudRepository.
Same with Department, Company etc...
What i want to do is, I will write a BaseRepository which gonna extend CrudRepository, base repository should accept all entities and do persistance operations.
Is there a way to that ??
Don't extend CrudRepository it's functionality is all tied to the generic type, it'd be hacky to extend it for a generic implementation. You probably just want something simple which uses the JPA entity manager directly:
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
public class GenericRepository {
#Autowired
private EntityManager entityManager;
public <T, ID> T findById(Class<T> type, ID id) {
return entityManager.find(type, id);
}
}

How to stream resultsets in spring Data JPA with custom criteria

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);
}

Understanding repositories in Spring Data

I want to create a "generic" repository that query data from multiple entities. If I do that:
#Repository
public interface MyRepository {
#Query("select r from Role r")
List<Role> getRoles();
}
I get an error because Spring doesn't find an implementation to inject when a MyRepository instance is required. So far, so good. Now, If I do this:
#Repository
public interface MyRepository extends JpaRepository {
#Query("select r from Role r")
List<Role> getRoles();
}
I get an error because Object is not a JPA managed type (JpaRepository is generic). Ok, again. If I do this:
#Repository
public interface MyRepository extends JpaRepository<User, String> {
#Query("select r from Role r")
List<Role> getRoles();
}
It works. Why? I'm declaring a JpaRepository for entity User, not Role. Why does JpaRepository need a concrete entity even when the queries will be against another one?
Every repository in Spring Data has to extend the Repository interface, that is a generic interface, so you always have to specify the entity you are gonna work with and you can't do anything about it because it is how Spring Data is implemented. You can find more information here about creating repositories:
http://docs.spring.io/spring-data/jpa/docs/1.4.0.M1/reference/html/repositories.html
On the other hand, of course you can specify one entity to the repository and then add methods that return other type of entities because in your interface you can add whatever you want (also notice that Repository interface has no methods). But if you want to use the methods of the parent interface you have to use the entity you specified.
In your example, you could do what #M. Deinum suggested and create a JpaRepository<Role, Long> and use the findAll query, that makes much more sense. Using a JpaRepository<User, String> as you are doing is just a misuse of the framework.

Deciding which implementation to inject

I have a Spring project, split into several modules.
data access library (spring-data-jpa; entities and repositories)
security library (spring-security; including an extended repository with #PreAuthorize annotations)
web project (depends on both libraries)
batch project (depends only on data, since there's no user to authenticate in Spring)
So in the data access library, I have this interface:
#Repository
public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
List<Item> findAll();
Item findById(Long id);
}
And in the security library:
#Repository
public interface SecuredItemRepository extends ItemRepository {
#PreAuthorize("hasRole('ROLE_ADMIN')")
List<Item> findAll();
#PreAuthorize("hasRole('ROLE_ADMIN')")
Item findById(Long id);
}
When I #Autowire an ItemRepository, I would like it to use SecuredItemRepository if it's available, and ItemRepository if not.
Is there a way to declare the SecuredItemRepository as the default choice, or first in the list of ItemRepository implementations to grab? I'd rather not specify the implementation in every location that I need to access the database.
And of course, two seconds later I find the answer. I needed to annotate SecuredItemRepository with this:
#Priority(value = Ordered.HIGHEST_PRECEDENCE)

Resources