Object attributes combination query Mongodb Repository - spring-boot

I am trying to query based on Object attributes combination in MongoDB:
My Object looks like:
#Getter
#Setter
class Person {
private String name;
private String email;
private Address address;
}
Address entity looks like:
#Getter
#Setter
class Address {
private String city;
private String state;
private String postal;
private String country;
}
Assume that above classes are also annotated with necessary attributes required for MongoDB collections.
Now when I am about to query from a PersonRepo interface that extends MongoRepository, as:
public interface PersonRepo extends MongoRepository<Person, String> {
}
The objective is to fetch all result-set where Address matches any combination of city, state, postal or country. For example, I want to fetch all results where city=XYZCity, state = ABCState, Postal might not be provided and country might be DEFCountry.
Address can be in any combination and whatever combination matches, the result-set could be produced.

Related

Filter based on Integer Comparison in Spring data redis

I am using spring-data-redis to communicate with database.
I have entity class like below
#RedisHash(value = "employee")
public class Employee
{
#Id
private long id;
#Indexed
private String name;
#Indexed
private int age;
private Address address;
...... ...... ......
}
I want to filter the employees based on age group. For example, age lesser than 35 (age<35). How to achieve this in below repository?
#Repository
public interface EmployeeRepo extends CrudRepository<Employee, Long>
{
public Employee findByName(String name);
}
I dont prefer to load complete data from table and do search using any loop/stream.
I don't think it does. I tried to implement what you tried to do using
#Index
long lastUpdatedOn;
when I checked the redis it gives a key entity:lastUpdatedOn:160.... and I tried searching for it using ZRANGE which gives no results.

How to Inner Join using Spring Boot JPA / Hibernate in Repository?

I am currently learning spring boot , hibernate and Spring Boot JPA
I developing a Classroom App for coaching centers and institutes .
In it, students enrolled to multiple courses in a single institute
The Student Entity class :
#Entity
#Table(name = "student")
public class Student {
private String name;
private String dob;
private String gender;
private String address;
private String email;
private Integer mobile;
private String joined;
private Integer instID;
#Id
private String studentid;
getters and setters()....
}
Course Table Entity class
#Entity
#Table(name = "courses")
public class Course {
private String name;
private String description;
private String logo;
private String start;
private String end;
private Integer fee;
#Id
private String courseid;
private Integer instID;
getters and setters();
}
Enrolled Classes Table's Entity class
public class EnrolledCourses {
#Id
String enrollID;
String courseid;
String studentid;
Date joined;
getters and setters()...
}
JPA Repository
#Repository
public interface StudentRepository extends CrudRepository<Student, String> {
Student findTopByInstIDOrderByStudentidDesc(int instID);
}
#Repository
public interface CourseRepository extends CrudRepository<Course,String> {
}
#Repository
public interface EnrolledRepository extends CrudRepository<Course,String> {
}
My Need
Now I am retrieving enrolled students for a given course in a given institute... by using this MySQL query
SELECT
`enrolled_courses.enrollID`,
`student.name`, `student.studentid`
FROM `enrolled_courses`
INNER JOIN `student`
WHERE
`enrolled_courses.studentid` = `student.studentid`
AND
`student.instID` = 13
AND
`enrolled_courses.courseid` = '13I01C' ;
Now I need to implement this Inner join query in CourseRepository (or enrolledstudent repo)
How to achieve this ?
Please guide me
If we use hibernate mapping in EnrolledCourses entity like
#Entity
public class EnrolledCourses {
#Id
String enrolledId;
#ManyToOne
Student student;
#ManyToOne
Course course;
Date joined;
getters and setters()...
}
from the above mappings without using any SQL queries, you can retrieve all student who comes under a particular course
By using the method in the interface
#Repository
public interface EnrolledRepository extends CrudRepository<EnrolledCourses,String> {
List<EnrolledCourses> findByCourse_CourseId(String courseId);
}
if we have some relations between the entities we can easily retrieve all the fields using Jpa.

Retrieving foreign key attributes in DTO

I am using java+Spring framework+Hibernate for creating rest api but I have stumbled upon retrieving details of a table using foreign key attributes.
I have the following tables::
https://i.stack.imgur.com/lG7UR.png
I am retrieving all the ratings given using product id and then mapping to DTO, now I also want to populate the username using idusers as this is my foreign key.
Same is the case when I try to retrieve ratings given by the users, instead of displaying idproducts I want to display the product name and product description as It is a foreign key.
Any advice on how to do so using DTO's.
This is a perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
Assuming you have an entity model like this
#Entity
public class User {
#Id
Integer id;
String role;
String username;
String password;
boolean enabled;
}
#Entity
public class Product {
#Id
Integer id;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
#OneToMany(mappedBy = "product")
Set<Rating> ratings;
}
#Entity
public class Rating {
#Id
Integer id;
int rating;
String review;
String ratingscol;
#ManyToOne(fetch = LAZY)
Product product;
#ManyToOne(fetch = LAZY)
User user;
}
A DTO mapping for your model could look as simple as the following
#EntityView(Rating.class)
interface RatingDto {
Integer getId();
UserDto getUser();
ProductDto getProduct();
}
#EntityView(User.class)
interface UserDto {
Integer getId();
String getUsername();
}
#EntityView(Rating.class)
interface ProductDto {
Integer getId();
String getProductName();
String getProductDesc();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
RatingDto dto = entityViewManager.find(entityManager, RatingDto.class, id);
But the Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
It will only fetch the mappings that you tell it to fetch
You can use ModelMapper when converting a DTO to an Entity bean and back from Entity bean to a DTO.
Add ModelMapper to your project
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.5</version>
</dependency>
Define the ModelMapper bean in your Spring configuration
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
Assuming the following models based on the given ER diagram you have given
public class UserDto {
Integer userId;
String role;
String username;
String password;
boolean enabled;
...default and parameterized constructor
...getter and setter methods
}
public class ProductDto {
Integer productId;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
...default and parameterized constructor
...getter and setter methods
}
public class RatingDto {
#Id
Integer id;
int rating;
String review;
String ratingscol;
ProductDto productDto;
UserDto userDto;
...default and parameterized constructor
...getter and setter methods
}
You can retrieve the ratings of a product using product id along with the user details by using the following method
#Repository
public interface RatingRepository extends JpaRepository<Rating, Integer>{
List<Rating> findByProduct_ProductId(Integer productId);
}
Then mapping rating objects to DTO
RatingDto ratingDto = modelMapper.map(rating, RatingDto.class);
Now you can retrieve username as following
ratingsDto.getUserDto().getUserName()
The same way you can retrieve the ratings by userId and access product details

Redis #Reference does not work in Spring Data Redis

I am facing issues while implemeting #Reference in Spring Boot + Spring Data Redis. Address is a List in Employee and when I saved the office and home address and I was expecting the data to be saved with the Employee. But data did not get saved and hence unable to search the Address using street.
Employee.java
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#RedisHash("employees")
public class Employee {
#Id #Indexed
private String id;
private String firstName;
private String lastName;
#Reference
private List<Address> addresses;
}
Address.java
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#RedisHash("address")
public class Address {
#Id
private String id;
#Indexed
private String street;
private String city;
}
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EmployeeAdressTest extends RepositoryTestSupport{
#Autowired private EmployeeRepository employeeRepository;
#Before
public void setUp() throws JsonProcessingException {
Address home = Address.builder().street("ABC Street").city("Pune").build();
Address offc = Address.builder().street("XYZ Street").city("Pune").build();
Employee employee1 = Employee.builder().firstName("Raj").lastName("Kumar").addresses(Arrays.asList(home, offc)).build();
employeeRepository.save(employee1);
List<Employee> employees = employeeRepository.findByAddresses_Street("XYZ Street");
System.out.println("EMPLOYEE = "+employees);
}
#Test
public void test() {
}
}
Spring Doc:
8.8. Persisting References
Marking properties with #Reference allows storing a simple key reference instead of copying values into the hash itself. On loading from Redis, references are resolved automatically and mapped back into the object, as shown in the following example:
Example 30. Sample Property Reference
_class = org.example.Person
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand
lastname = al’thor
mother = people:a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56
Reference stores the whole key (keyspace:id) of the referenced object.
?
Spring Data Redis requires you to save the objects stored in home and office separately from the referencing object employee1.
This is (now) stated in the official documentation at the very end of chapter 8.8: https://docs.spring.io/spring-data-redis/docs/current/reference/html/#redis.repositories.references
So if you save home and office to the database before saving employee1 you should be fine.
The same btw holds valid for updates you make to referenced objects later on. Just saving the referencing object alone does not save the updates on the referenced objects.

How to search through array in Spring Boot CrudRepository

Say, I have the following entity class:
Person.java
#Entity
public class Person {
#Id
private String name;
private String[] cars;
// Constructor, getters and setters
}
And the repository:
PersonRepository.java
public interface PersonRepository extends CrudRepository<Person, String> {
// this is unclear!
List<Person> getAllByCars...(String car)
}
Is there a method that returns all persons, whose car array contains one given car (the String parameter above)?
For me, it seems that all supported JPA keywords can only deal with single elements, but not with arrays.
Thanks for help!
Ideally, You should declare cars as a separate Entity like this
#Entity
public class Person {
#Id
private String name;
private List<Car> cars;
// Constructor, getters and setters
}
If not you should change Array to List at the least.
change
private String[] cars;
to
#ElementCollection
private List<String> cars;
Then You have to write a Query like this
#Query("select p from Person p WHERE :car in elements(p.cars)")
List<Person> getAllByCars...(#Param("car") String car)
I'm guessing at how you are currently storing the cars information and suggesting a possible solution:
#Entity
public class Car {
#Id
private String name;
#Column
private String person_name;
}
public interface CarRepository extends JpaRepository<Car, String> {
//Result will have all cars with the person_name identifying the Person #Entity
List<Car> findByName(String name);
}

Resources