How to write a Custom JPA method to search a database record using fields name - spring-boot

Here i am working in Spring Boot. Now i am creating API's for CRUD Operations. Also i need to write a code for Searching the database record using fields name. Here i am working with "Products" table. the table contains fields like "itemCode", "hsCode", "itemCategoryId","productDescription","brand","countryOfOrigin","uom","retailSellingPrice","exciseTaxPercentage","assignedTo","assignedBy",...etc.
So, if the user gives the input as the brand, uom, retailSellingPrice. i should use a Query like "SELECT * FROM PRODUCTS WHERE brand=:brand, uom =:uom,retailSellingPrice=:retailSellingPrice ".
I write a Custom JPA method like findByuomContainingOrRetailSellingPriceContainingOrBrandContaining(parameter1, parameter2, parameter3);
But is there any other approach to search the products using fields so that if 10 searching fields is there, then my custom method will be small only.
Please give me some suggestions

You can create your own custom repository and give method name whatever you want(a small one).
You can create a custom repository like below :
Assuming that you have a ProductRepository implements CrudRepository<Product,Long>
Create an interface like #Your_repository_name{custom} (ProductRepositoryCustom) and give method name whatever you want with required parameters.
Create implementation class for ProductRepositoryCustom interface. You can name it whatever you want, but it will be good if you follow some convention. Do it like #Your_repository_name{Impl} (ProductRepositoryImpl)
Extend ProductRepositoryCustom from ProductRepository(ProductRepository implements CrudRepository<Product,Long>,ProductRepositoryCustom)
Now you can call method of ProductRepositoryImpl from the same object you call the methods of ProductRepository.
#Autowired
private ProductRepository productRepository;
Use productRepository to call methods of Impl clas.

Take a look at JPA's Query by Example. QueryByExampleExecutor interface is extended by JpaRepository. It has a few methods for searching by example. Here is a simple example,
Let say Product is an entity representing Products table, then you can do something like this,
Product product = new Product();
product.setItemCode(...);
product.setHsCode(...);
...
Example<Product> example = Example.of(product);
Iterable<Product> = repository.findAll(example);
You can find a concrete example here.

Related

Spring Data- how to tell spring what entities to retrieve

If i have several entites, lets say :
#Entity
class Book{
String name;
Author author;
}
#Entity
class Author{
String name;
City hometown;
}
#Entity
class City{
String cityName;
}
If i want to retrieve all the books, if i use classic JPA Repository and Spring Data and just do a findAll(), it will get me all the books with all the Authors with all their home towns. I know i can use #JsonIgnore, but i think that only prevents whats being returned, not whats being looked up in the database. And also i have methods that DO want to return both books and authors, so #JsonIgnore -ing does not work for me. Is there anything like this ? To tell Spring Data what to look up and what to return ? Any links or guides or methods i don't know of, would be appreciated.
Spring Data has the concept of 'projections' which allow you to return different representations of the same Entity.
Official 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 create projections based on certain
attributes of those types. Spring Data allows modeling dedicated
return types, to more selectively retrieve partial views of the
managed aggregates.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
Where a Projection is a 'closed' projection (a projection interface whose accessor methods all match properties of the target aggregate) then the documentation notes that additionally:
Spring Data can optimize the query execution [to select only the relevant fields], because we know about
all the attributes that are needed to back the projection proxy
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.interfaces.closed
Spring Data also allows for Projections to be specified dynamically at runtime. See further:
https://github.com/spring-projects/spring-data-commons/blob/master/src/main/asciidoc/repository-projections.adoc#dynamic-projections
First mark your relations as LAZY
Then specify what data needs to be fetched on a per-query basis.
See for example:
https://vladmihalcea.com/eager-fetching-is-a-code-smell/

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

MVC architecture - patterns

I need some help with MVC architecture. I use the following architecture for an object named User.
UserRepository -> IUserRepository -> UserService -> IUserService -> UserController
The User object comes from my database and I'm using EntityFramework. I have a function that returns a list of users Return_All_Users(). One of the fields that gets returned is "UserType". This comes out as a number, but when I show the list in my Index.aspx page, I would like it to show as a string. The number for "UserType" needs to look into a Dictionary to find the string that goes along with the number like "Administrator" and I would like this string to show in my Index page.
How would I go about doing this? I'm currently using this function:
public IEnumerable<User> Return_All_Users()
{
//my code here
}
I had another post for a similar question, and it was suggested that my IEnumerable should return a string, not the User object. I tried that, but then I'm working with a Dynamic model and I didn't want to do that. Nor do I know how to work with a Dynamic model, so I thought maybe there is a better way of doing this.
Should this happen in my UserService? Maybe I need to create a new class called NewUser, and define the UserType as a string, then instantiate a new NewUser and pass the value from User. Before the UserType is passed, I would look in the dictionary and get the correct value for the key.
Should I do that, or is there a better way?
After I posted this question, I just thought of doing this with a stored procedure. Maybe use a stored procedure in my database to return the data, as opposed to looking up my data straight from my database table.
I would create a View Model UserView that was formatted to the representation of how your view would best use that data. You could perform the mapping from User to UserView within your Repository or Controller depending on where you prefer doing this kind of mapping.

generic class constraints: 2 types

i want to create a generic class that would accept T.
T is an object coming from Entity Framework representing a Table, or a View of that table.
properties on both would be the same.
I would like to create a generic class, that will accept the table or view, and construct a linq query based on the properties.
so i would need to do something like..
class Foo Where T : myTable or T : myView
so that later i could use the strongly typed properties to construct my predicates.
How could i achieve something like this?
the way i construct my query looks something like this:
if (critera.IsTradeDate)
predicate = PredicateUtility.And(predicate, t => t.DateTrade >= critera.FromDate);
the t is the type that needs to be strong, and properties used will be the same on table and view. So in this case, t should represent either my table or my view, to re-use the code, but still leverage entity framework..
Create an interface ITableOrView (or some better name). Apply the interface to both partial classes for your Entities that are the Table or View.
Create your generic class with where T : ITableOrView
Now you can use the interface types.
BUT you can't use interfaces in many places in Entity Framework queries so you'll actually need to delegate that work back to the 'T' class itself.

Resources