Spring Boot REST application; findBy method using foreign key - java

Using Spring Data REST, I have two models, NvdApps with a one-to-many relationship to NvdVulnerabilities
I'm trying to add the ability to search NvdVulnerabilities by an NvdApp, so my repository looks like this:
public interface NvdVulnerabilityRepository extends PagingAndSortingRepository<NvdVulnerability, Long> {
List<NvdVulnerability> findByNvdApp(NvdApp nvdApp);
}
And this gives me the REST end point:
"findByNvdApp" : {
"href" : "http://localhost:8080/api/nvdVulnerabilities/search/findByNvdApp{?nvdApp}",
"templated" : true
}
When I try to use this end point, it just returns the entire table, regardless of what I put in the query string. Example URL's I've tried:
http://localhost:8080/api/nvdVulnerabilities/search/findByNvdApp?nvd_app_id=25
http://localhost:8080/api/nvdVulnerabilities/search/findByNvdApp?25
http://localhost:8080/api/nvdVulnerabilities/search/findByNvdApp?NvdApp=25
Am I missing some configuration? I'm basically trying to replicate the query:
SELECT * FROM NVD_VULNERABILITY where nvd_app_id = 25
Which works as intended in the H2 database console. How exactly does the search end point work, and how do I get it to filter as intended?
I'd also like to have the paging work with the search endpoint; right now it returns the entire 7k+ rows whereas the end point http://localhost:8080/api/nvdVulnerabilities/ returns 20 items per page

You can try:
List<NvdVulnerability> findByNvdApp_Id(Integer id);
If Integer id variable exists in your NvdApp class.

Changing the repository query to match below:
public interface NvdVulnerabilityRepository extends PagingAndSortingRepository<NvdVulnerability, Long> {
Page<NvdVulnerability> findByNvdApp_Id(Long id, Pageable pageable);
}
allows searching by id as well as making the return paginated

Related

JpaSpecificationExecutor, how to change the field in SELECT

dears.
Currently, I am working with JpaSpecificationExecutor API, cause I need to create dynamic queries based on a lot of optional search criteria, for this I am starting with a root entity, which is included in the generic type in the JpaSpecificationExecutor interface.
The code to make the build in the Specification (which is included in the findAll method that belongs to repository interface) is the following:
public Specification<T> build(){
return (root, query, criteriaBuilder) -> {
Predicate filters = null;
//createPredicate is a method to create predicates (it does not matter in this code)
filters = createPredicate(root, criteriaBuilder, searchCriterias);
return filters;
};
}
Now each is working fine, but there is a little detail, in the query I am using joins to make relation with other entities, but when I get the response, like in this code:
List<EXAMPLE> examples = repository.findAll(filters.build());
I am not able to see the filter data in other entities, just I can see the field in the root entity (It is EXAMPLE entity) because these ones are appearing in the query formed. so, I would like to include in the SELECT the other entities, in order to see the filter data by means of the JOINs, but until now I have not been able to do it.
I have seen in any inputs, that I can use these codes in my build code, I have tried, but the new files are not appearing in the generated query:
query.select, or query.multiselect
Ref:
Ref. 1
Also, I have found that this is not working with JpaSpecificationExecutor, because the list of attributes in the SELECT is assigned by the entity Ref. 2
My question is, does someone know if exists another way to change the field in the SELECT with JpaSpecificationExecutor.
Regards.

How to query multiple entries at once

I am using spring boot reactive and Couchbase
Flux<Item> findByLocation_LocationIdOrderByCreatedAtDesc(String locationId);
Just to point here I am accessing Location.locationId. Location object has locationId field in main document
Also below properties is not printing the generated Couchbase query, if anyone can help with that too,
logging:
level:
org.springframework.data: DEBUG
The response is fine when database has only one entry, but when the db has more than one entry matching criteria it throws "Source emitted more than one item" .
My controller is returning
Flux<Item>
Following two annotations are mandatory or it keep returning the exception
#N1qlPrimaryIndexed
#ViewIndexed
#Ghrissology I already had ReactiveCouchbaseRepository
Normally, the spring Data change the query based on the return type.
if you want one result it use getSingleResult() automatically :
Item findByLocation_LocationIdOrderByCreatedAtDesc(String locationId);
in you case, i think he didn't understand the return type because you didn't implement a ReactiveCrudRepository:
public interface ReactiveItemRepository
extends ReactiveCrudRepository<item, String> {}

How to use getById method to get the a corresponding name in Spring MVC?

I'm learning Spring MVC and I want find a car via an id but get in return the name.
In my service class I call a generic method getXXXById. This is something JPA gives me by nature.
I know that I get the whole entity but how can I just receive the corresponding name to the id.
Example: I call getCarById(2) and it gives me back Tesla.
My Table:
id | Name
----------
1 | Ford
2 | Tesla
My Service:
class CarService {
// code ...
public Optional<CarEntity> getCarById(int id) {
return carRepository.findById(id);
}
There are two options to do that.
Making your own query
You could write your own query in JQPL to retrive only names.
For example you could create method like that in your repository.
#Query("select t.name from CarEntity where id = ?1")
public String findNameById(Integer id);
more information on this feature of Spring Data Jpa HERE
Projections
Second option is to make projection. As it is written in documentation
Spring Data query methods usually return one or multiple instances of the aggregate root managed by the repository. However, it might sometimes be desirable to rather project on certain attributes of those types. Spring Data allows to model dedicated return types to more selectively retrieve partial views onto the managed aggregates.
In simple words, it allows you to aggregate your results form queries in some limited set of attributes rather then whole entity.
Specifically for your needs I'd suggest to use first approch, but it is worth to know both.

Why need #Query when I can write a method in Spring JPA

I just got started with Spring JPA and I am reviewing code written by my coworker.
I see that he has been using the following code to find a Login object using username:
public interface LoginDao extends JpaRepository<Login, Long> {
#Query("SELECT u FROM Login u WHERE LOWER(u.username) = LOWER(:username)")
Login findByUsername(#Param("username") String username);
}
Cant he just create a method like this:
#GET
#Path("{username}")
public Login getOne(#PathParam("username") String username) {
Login login = loginDao.findOne(username);
if (login == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
} else {
return login;
}
}
What are the fundamental advantages of using #Query rather than writing a method approach. Or am I plain wrong and both have different purposes.
I personally dont want to write queries inside the code. I think mixing java with sql queries can make code look uglier.
Our stack is java, JPA, Jersey, JAX-RS, Postgreql, Spring Boot, Hibernate
Regards
First, This is not an SQL query, this is a JPQL one. It would be a native SQL query if the nativeQuery attribute was set to true, which is not the case by default.
It is perfectly fine to create queries with JPQL, you will be able to switch from Hibernate to Eclipse Link or another JPA implementation without issues. You should also be able to switch from Postgres to MySQL, SQL Server...
You have to start to worry if your coworker creates queries with #Query(nativeQuery = true, value = "..."), otherwise it looks fine to me.
Second, when you look to your repository declaration, you can see that the ID field for your Login entity is of type Long. That means the loginDao.findOne(..) method wants a Long parameter. Probably a surrogate key which is not username.
This is why your coworker created this new method: to find a Login row by something else than the Long surrogate key. (Here by username which is most likely a business key, but I do not know your application.)
Just for your information: Spring automatically creates queries with the signature of your repository methods (derived queries). For example:
public interface LoginDao extends JpaRepository<Login, Long> {
Login findByUsername(String username);
}
Spring JPA will automatically create a query looking for a field named username and create a WHERE clause with it.
Notice that it is not the same than your coworker query because it will not use the LOWER function.
Some anchors in the JPA documentation about those derived queries:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords
Another thing about your title:
"Why need #Query when I can write a method in Spring JPA"
Well this #Query writes a method in Spring JPA. :^)
JPARepository has come up with some of the Supported keywords which will write the queries themselves based on your entity.
If we are looking something out of box from what JPARepository provides #Query is useful like - Joining multiple queries, writing native queries etc.
From your code snippet both would do the same
For more info you can refer - https://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/jpa.repositories.html

how to add group field in #Query annotation in Solr

I have added a method to get quarters my repository class based on the value of book and year
public interface Repository extends SolrCrudRepository<Doc, Long> {
#Query(fields = { Constants.QUARTER_FIELD })
public List<CodingClinicDoc> findQuarterByBookAndYear(String book, int year);
}
but i am getting duplicate values e.g. 'First quarter' around 10 times
Please tell me if there is a way to apply group field like group=true&group.field=quarter to #Query annotation to get unique result.
Or some other way to get the distinct quarters.
As of version 1.5.2 of Spring Data Solr, you cannot use result grouping with SolrRepository. You'll have to use SolrTemplate.
See this section (http://docs.spring.io/spring-data/solr/docs/1.5.2.RELEASE/reference/html/#solr.misc.group) on Spring data solr reference.

Categories