How Spring data jpa #Query annotation works - spring

I am new to both Spring data and JPA. I am curious how the query annotation works. Like in my scenario I need all the userIds of an organization. So this is what i did:
#Query("select o.userId from User o where o.orgId = :orgId")
List <Integer> findUserIdsByOrgId(#Param("orgId")int orgId);
The above statement works fine. I get a list of user Ids. The problem is when I alter the query to search for the User
#Query("select o from User o where o.orgId = :orgId")
List <Integer> findUserIdsByOrgId(#Param("orgId")int orgId);
As I remove userId from o.userId the whole object is returned and not an Integer.
My assumption is that an error should be thrown if the return type is not matched to the one in the query.

The thing is that generics in Java are removed in runtime.
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
So Spring cannot make a check for generic type and trusts you that you don't mismatch type. Of course, if you return Integer instead of User (without generics) then Spring would throw an error.

Change the return type from List<Integer> to List<User> and it should work fine.

Related

Reserved Words in Derived Query Method Names in Spring

I have a column named nameOrSurname and I want to have a method in my repository like findByNameOrSurname but I get the following exception: org.springframework.data.mapping.PropertyReferenceException: No property name found for type ...
How do I do that?
The default lookup method strategy is CREATE_IF_NOT_FOUND, which considers first custom queries you have written. In that case if your entity that you retrieve is Customer I would have defined the HQL query by myself so that, jpa does not try to create the query by the name of the method which fails
#Query(value = "FROM Customer c where c.nameOrSurname = ?1")
List<Customer> findByNameOrSurname(String nameOrSurname);
Otherwise I think you are doomed to refactor your field name.
Here is just for reference all the reserve keywords for spring JPA repository

Handling filtering by a particular field in JPA Spring Boot

I want to implement a filtering feature based on the properties of an entity that I have stored in my db.
I'm using a JPA query to do so. The problem that I'm facing is concerned with entity manager which requires the class of the object that is required to return.
public List<CountryEntity> getSortedCountries(String field, String type) {
return entityManager.createQuery(GET_ALL_SORTED.concat(field).concat(" " + type), CountryEntity.class).getResultList();
}
When I select only one field, let's say the name of the country, the query returns a String and not an object of type CountryEntity.
What is the best approach to handle this problem? Should I create classes for every single case or is there another way that I'm missing?

how should i get data from mongo db using spring mongo repository?

i am using mongodb in my spring boot application and i am using mongo repository interface to get data from the database this is the way i am getting the data .
School sch=repository.findOne("id");
this will give me the school object then i can get all the data from there but my question is will it affect my application's performance if i get the whole object everytime i need some data from that object even if i need some fields . if so what will be the method to do that i searched and i see that using Query annotiation i can limit the fields but even then it give whole object it put all the other fields null and data is only at fields which i specify . any guidence will be helpfull .
You can use a projection interface to retrieve a subset of attributes.
Spring Data Mongo DB
interface NamesOnly {
String getName();
}
interface SchoolRepository extends Repository<School, UUID> {
NamesOnly findOneById(String id);
}
So after reading the documentation and reading other options this is the only solution i find where i can search the result using id and get only field i want in the result since i am only searching using the id so i have to overload the findbyId and since projection interface only change the return type i can not use that so here is what i did .
#Query(value="{_id:?0}",fields="{?1:1,?2:1}")
List<School> findById(String schoolId, String fieldOne,String fieldTwo);
here ?0 is a place holder for schoolId and ?1 and ?2 are the placeholder for the fields name so now i can create these overloaded method which i can use to any no of fields the output is list of school since i am using id which is primary key so its just one school object list so i can just do get(0) to get my school object and it will have all the other fields as null this is the best i could find please share your thought to improve it i would love to hear other solutions .

Springboot JPA #Query Rest Giving PersistentEntity must not be null

I am trying to put together a simple rest service with springboot 1.4.3. I have it up and running with simple queries like findByRecid, however when I try to do a #Query statement on that same entity, I get the below error message
{"cause":null,"message":"PersistentEntity must not be null!"}
Further, if I use a fully qualified name for the entity in the query, Intellij tells me that the class isn't an entity, even though it's marked with #Entity and works with the standard springboot queries. Please assist if possible - I've been trying to figure this one out for days. Below is the query for your reference
#Query("SELECT new com.test.domain.ReceivableBeans.RecAgeBucketGroupAmountSum(r.agebucket, sum(r.amount)) from com.test.domain.Receivable as r GROUP BY r.agebucket")
List<com.test.domain.ReceivableBeans.RecAgeBucketGroupAmountSum> recByAgeBucket();
Try:
#Query("select new ReceivableStats(r.agebucket, sum(r.amount)) from Receivable r group by r.agebucket")
List< ReceivableStats> recByAgeBucket();
or name your aliases in the query, e.g.
sum(r.amount) as amount
and have your method return an Object[].

Same query method and parameters with different return in Spring Data

I want to use projections in order to return less elements for the same queries.
Page<Network> findByIdIn(List<Long> ids);
Page<NetworkSimple> findByIdIn(List<Long> ids);
Since the queries are created using the name of the method, what options do I have to do the same query but with different name ?
I ran into this today, and the accepted answer is actually incorrect; you can change the method name without altering the behavior. According to the Spring Data documentation:
Any text between find (or other introducing keywords) and By is considered to be descriptive unless using one of the result-limiting keywords such as a Distinct to set a distinct flag on the query to be created or Top/First to limit query results.
Thus you can have a method named findByIdIn and another named findNetworkSimpleByIdIn and the two will return the same data (optionally converted to a different form depending on the defined return type).
Spring Data query via method is constructed by convention and you can't change the name and yet expecting a same behavior.
You can try to use #Query annotations which doesn't depend on the method name, or possibly implementing custom DAO using JPAQuery plus FactoryExpression which has the same effect as projections.

Resources