I'm about to create a stock-standard rest CRUD api and have taken note of the handy CrudRepository class given in the spring-data framework. I'm planning on also using spring to declare #RequestMappings to hook up the default crud operations to their URL counterparts (e.g. /customer/{id} --> CrudRepository.findOne({id}), etc).
Is there a spring utility class to acheive this or will i need to roll my own?
Ah ha! What I'm looking for is a org.springframework.data.rest.core.annotation.RepositoryRestResource located in the spring data rest webmvc project. maven co-ordinates: "org.springframework.data:spring-data-rest-webmvc"
an example extract from the documentation:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
enter code here
This repository is an interface and will allow you to perform various operations involving Person objects. It gets these operations by > extending the PagingAndSortingRepositry interface defined in Spring Data Commons.
At runtime, Spring Data REST will create an implementation of this interface automatically. Then it will use the #RepositoryRestResource > annotation to direct Spring MVC to create RESTful endpoints at /people.
Related
I'm building an application using Spring Data REST and implementing an interceptor pattern using a MappedInterceptor as suggested in this post. The interceptor works as expected and it intercepts #RestControllers.
Now, using the parameters available in the preHandle(…) method signature (these include: HttpServletRequest request, HttpServletResponse response, Object handler => can be casted to org.springframework.web.method.HandlerMethod), how can I access the RestRepository class or repository Method being invoked (the getMethod(), from the HandlerMethod class, works great with Concrete classes, but it does not work with Repository interfaces, it ends returning a RestAbstractController class that invokes the target repository through reflection)???
Why I need this?
Because, I´m doing a cross-cutting logic that needs to access the Repository interface to find a specific business annotation, if the annotation is present, some logic is done (like setting MDC special values, for example)...
Thanks...
The most flexible way to generically lookup and use Spring Data repositories is through the Repositories and RepositoryInvoker abstractions.
The former provides by-type lookup abilities of metadata about the repositories and the repositories themselves. The latter allows generic invocation of CRUD and query methods on those repositories. This additional abstraction is necessary as Spring Data repositories don't have to implement a special interface as long as they expose methods that are syntactically equivalent to the ones provided in Spring Data's CrudRepository.
The general way
If you know about the actual domain class you're trying to access the repository for you can get an instance of Repositories injected into your class. That one in turn allows you to lookup entity and repository information as well as the repository itself.
As the latter doesn't have to implement a dedicated interface mandatorily, Repositories.getRepositoryFor(…) only returns Optional<Object> which isn't too helpful if you want to actually do stuff on the repository. RepositoryInvokerFactory allows you to create RepositoryInvoker instances that allow you to invoke certain methods on a repository explicitly independent of way they're actually declared.
#Component
#RequiredArgsConstructor
class SomeComponent {
private final Repositories repositories;
public <T> void someMethod(Class<T> type) {
… = repositories.getEntityInformation(type);
RepositoryInvokerFactory factory = new DefaultRepositoryInvokerFactory(repositories);
RepositoryInvoker invoker = factory.getInvokerFor(type);
Optional<T> entity = invoker.invokeFindById(4711);
}
}
Note, that a Repositories instance is available as Spring Bean if you use Spring Data REST. If you don't simply declare a bean for it. All it needs is a ListableBeanFactory.
Spring Data REST
With Spring Data REST in the picture on might get into the need to lookup the repository that's backing a particular path segment of the URI. That additional knowledge is encoded in RepositoryResourceMappings which can be used to find out about the domain type that's accessed:
RepositoryResourceMappings mappings = … // get injected
Optional<Class<?>> domainType = mappings.stream()
.filter(metadata -> metadata.getPath().matches(pathSegment))
.findFirst()
.map(ResourceMetadata::getDomainType);
The discovered type can now be used to obtain the repository instance from Repositories. Spring Data REST also provides a preconfigured instance of RepositoryInvokerFactory that applies potentially registered custom EntityLookup instances. I.e. using that is preferred to creating an own one like shown above.
This question already has answers here:
How are Spring Data repositories actually implemented?
(1 answer)
How does Spring Data JPA work internally
(1 answer)
Closed 3 years ago.
I have a code like this:
Repository
#Repository
public interface EquipmentRepository extends JpaRepository<Equipment, Integer>{
Equipment findById(int id);
}
Service
#Service
public class EquipmentServiceImpl implements EquipmentService {
#Autowired
EquipmentRepository equipmentRepository;
#Override
public Equipment findById(int id) {
return equipmentRepository.findById(id);
}
}
I wonder that why i can call a method of 'interface EquipmentRepository'. EquipmentRepository is a interface, Right ?
Spring Repository is responsible for importing the DAO's into the DI container and also it makes the unchecked exceptions into Spring DataAccessException. The Spring Repository annotation is meta annotated with the #Component annotation so that the repository classes will be taken up for component scanning.
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.
A class thus annotated is eligible for Spring DataAccessException
translation when used in conjunction with a
PersistenceExceptionTranslationPostProcessor. The annotated class is
also clarified as to its role in the overall application architecture
for the purpose of tooling, aspects, etc.
Source: JavaDoc
but in your case you are also extending the JpaRepository of Spring Data JPA. Spring Data automatically provides implementations of common CRUD operations. The JpaRepository extends the interface CrudRepository which has the methods declared for all basic crud operations.
public interface EquipmentRepository extends JpaRepository<Account, Long> { … }
Defining this interface serves two purposes:
First, by extending JpaRepository we get a bunch of generic CRUD
methods into our type that allows saving Equipments, deleting them and
so on.
Second, this will allow the Spring Data JPA repository infrastructure
to scan the classpath for this interface and create a Spring bean for
it.
The #EnableJpaRepositories scans all packages below com.acme.repositories for interfaces extending JpaRepository and creates a Spring bean for it that is backed by an implementation of SimpleJpaRepository (spring data provides default imlpementations of CRUD repository through this class).
So that is why even when you haven't defined the method , you are able to do crud operations through this setup.
Refer : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.repositories
folks!
I have two maven modules in my application - domain and persistence.
Domain has a domain object, services and "data provider" interfaces to external endpoints, for example, persistence. Domain contains business logic and has no external dependencies - he know nothing about persistence.
Persistence depends on domain. It implements "data provider" interfaces from domain module. It may be relational db implementation, nosql implementation, file implementation etc.
For example, I have interface PersonRepository in domain, like this:
public interface PersonRepository {
List<Person> findAll();
List<Customer> findByLastName(String lastName);
}
I want to implement data provider interface with Spring Data JPA. I need to write something like that:
public interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findAll();
List<Person> findByLastName(String lastName);
}
But I don't want to inject spring dependencies to "core domain". I want to stay my domain very lightweight and independent.
Is there way to implement PersonRepository with Spring Data in Persistence module?
Instead of extending the ready-made interfaces by Spring Data you can just copy the methods in your own interface. Normally you would just put a #Repository annotation on it and Spring Data would do its job. But that would reintroduce the dependency.
So what you could do instead is in your Spring Configuration invoke the JpaRepositoryFactory.getRepository yourself. Something like this should work:
#Bean
public PersonRepository(RepositoryFactorySupport factory) {
return factory.getRepository(PersonRepository.class);
}
This will be either in your persistence module or in a third module which does the wiring of all your modules, so the dependencies shouldn't be an issue.
The Spring Data JPA interface can extend multiple interfaces. Something like the following should work.
Defined in your domain module:
public interface PersonRepository {
List<Person> findAll();
List<Customer> findByLastName(String lastName);
}
In your persistence module:
#Reposistory
public interface SpringDataJPAPersonRepository extends CrudRepository<Person, Long>, PersonRepository {
// Any Spring Data JPA specific overrides e.g. #Query
}
I'm developing a web application using MVC architectural pattern.
Struts2 (version 2.3.24) is used for the Business Logic and Presentation Layer
Spring (version 4.1.0) is the dependency injection engine
Hibernate (version 3.6.10) is used for the Data Layer.
I have to create a PaginationFactory class that I can dynamically use for the various section of the application. I've several examples on google and StackOverflow... But mostly old stuff like this question.
Any ideas on how implement this function with using something more modern? Maybe with JQuery and Ajax as support?
I suggest for you to use Spring Data Jpa, it's already have implemented pagination.
Your repository will look like this:
public interface MedicamentRepository extends JpaRepository<Medicament, Integer> {}
You can extend, as example, PagingAndSortingRepository interface, if you don't need some of methods that JpaRepository provides.
public class SomeClass{
#Autowired
public MedicamentRepository medicamentRepo;
public void someMethod(){
//in spring data jpa, page count starts from 0;
PageRequest pageRequest = new PageRequest(pageNumber,
pageSize); //also have sorting
org.springframework.data.domain.Page<Medicament> page = medicamentRepo.findAll(pageRequest);
}
}
you can read more here
I want to understand a project's DAO layer, it's developed with Spring Data JPA.
I will take the entity user as example. So I have this Interface named
userRepository extends JpaRepository<user, Long>
What's the (User, Long) for? And secondly
#Query("select u from user u where u.login = :login")
User findUserByLogin(#Param("login")String login);
I can't find an Implementation of this Interface in the project. Are we going to work with this Interface directly to get data from DB?
According to spring data jpa documentation:
The central interface in Spring Data repository abstraction is
Repository. It takes the domain class to manage as well as the
id type of the domain class as type arguments
So, Utilisateur, Long represents that your entity is Utilisateur and Long is the type of your primary key.
Regrading to your second question, spring offers default implmentations of those interfaces by creating proxy instances for them. Take a look at spring data docs.