Handling filtering by a particular field in JPA Spring Boot - 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?

Related

How to return model object from jpa query

I'm developing a Spring Boot application with Spring Data JPA. I want to return the promedio field when the calificacionSemestral1 field is a specific value and the calificacionSemestral2 field is a specific value.
Entity
DER
Doing this using JPQL is it possible?
I know that I can create a DTO with the same fields or do two queries, but I want to avoid doing it if I can get the result in a single query.

How to handle multiple request params in spring boot?

Suppose I have a Employee class. It has got many fields like id, firstName, lastName, designaton, age, salary and other fields too. Now I am making a Get Query where I want to use all of these fields (required=false) to be passed as Request Params.
But the question is, there could be many combinations like (firstName,age) or (age,salary,lastName) or (designation,age,salary,lastName) and many more like this. So how should I handle all this filters. Shall I have to write each query for each case?
PS: I am using Spring Boot with Spring Data Jpa.
For this you will have to send Object from where you can get your combination. There may be many combination. So from this perspective you will send value as object and for database query you will select your combinations from that object.
If you want different combination, it won't be a good practice to write controller for every combination. So you can send a Object instead of RequestParam value where you can get your combinations from the Object
Example :
Class Employee{
// Your class instance variable
// Which is called your combinations
}
public Employee getEmployeeByName(Employee employee){
// now you send your desired combination from employee class for
// database query
}
Where you have too many fields, it's not a good practice to send all fields as RequestParam. Think of your class getting bigger day by day and you editing the controller method continously.
Better way is send as a object. No need to edit controller later. Only change the entity class

Mongo Spring #Document annotation

I'm trying to work with MongoTemplate and Spring and while looking on some other peoples code I was that everyone uses #Document annotation.
I did not used it at all up until not and everything worked fine for me.
I'm afraid I'm missing something and could not find any specific detailed information about the benefits of #Document annotation.
#Document is an annotation provided by Spring data project.
It is used to identify a domain object, which is persisted to MongoDB.
So you can use it to map a Java class into a collection inside MongoDB.
If you don't use Spring Data, you don't need this annotation.
I wrote a German blog post about how to use Spring Data for MongoDB - #Document is used there also:
https://agile-coding.blogspot.com/2020/10/keine-ahnung-von-mongodb-dann-nimm.html
This annotation serves only for specifying collection properties.
You can basically create simple class without any annotation needed.
Document annotation serves you for example when you are not happy with autogenerated collection name. If you do not specify #Document annotation, you still have the same result, for example
[
{
"_id": {"$oid": "62b43525de57ec7dec41a286"},
"_class": "com.example.demo.Person",
"name": "Adam"
}
]
This annotation may however be important for some kind of annotation based process to target which document are in use (maybe for indexing and so on)
Same goes for Id annotation:
if you do not provide any id specification, Id field is automatically added by mongo
if you have field named as "id" of type BigInteger, ObjectId or String, then this field is automatically populated after insert
From the docs https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo-template.id-handling
11.5.1. How the _id Field is Handled in the Mapping Layer
MongoDB requires that you have an _id field for all documents. If you
do not provide one, the driver assigns an ObjectId with a generated
value. When you use the MappingMongoConverter, certain rules govern
how properties from the Java class are mapped to this _id field:
A property or field annotated with #Id (org.springframework.data.annotation.Id) maps to the _id field.
A property or field without an annotation but named id maps to the _id field.
The following outlines what type conversion, if any, is done on the
property mapped to the _id document field when using the
MappingMongoConverter (the default for MongoTemplate).
If possible, an id property or field declared as a String in the Java class is converted to and stored as an ObjectId by using a Spring
Converter<String, ObjectId>. Valid conversion rules are delegated to
the MongoDB Java driver. If it cannot be converted to an ObjectId,
then the value is stored as a string in the database.
An id property or field declared as BigInteger in the Java class is converted to and stored as an ObjectId by using a Spring
Converter<BigInteger, ObjectId>.
If no field or property specified in the previous sets of rules is
present in the Java class, an implicit _id file is generated by the
driver but not mapped to a property or field of the Java class.
When querying and updating, MongoTemplate uses the converter that
corresponds to the preceding rules for saving documents so that field
names and types used in your queries can match what is in your domain
classes.
Some environments require a customized approach to map Id values such
as data stored in MongoDB that did not run through the Spring Data
mapping layer. Documents can contain _id values that can be
represented either as ObjectId or as String. Reading documents from
the store back to the domain type works just fine. Querying for
documents via their id can be cumbersome due to the implicit ObjectId
conversion. Therefore documents cannot be retrieved that way. For
those cases #MongoId provides more control over the actual id mapping
attempts. Example 62. #MongoId mapping
public class PlainStringId { #MongoId String id; }
public class PlainObjectId { #MongoId ObjectId id; }
public class StringToObjectId { #MongoId(FieldType.OBJECT_ID) String id; }
The id is treated as String without further conversion. The id is
treated as ObjectId. The id is treated as ObjectId if the given
String is a valid ObjectId hex, otherwise as String. Corresponds to
#Id usage.

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 .

is it possible to have conditional #Transient field?

Let's say if I have an Entity named person with lots of information including SSN. When other user query this person, I want to show a 'lite' version of person Entity. I could've done so by annotating SSN with #Transient, but that means the person himself would not get this field too. Is it possible to reuse the same Entity but return two different json to client? I'm using spring boot.
First of all #Transient just means that the value, the SSN in your case, won't be persisted to the database.
As for your problem annotations are static and cannot be applied dynamically.
You have 2 Options:
Define a new View class for your user.
Look at JacksonJsonViews

Resources