Get all the collection in document - spring-cloud-gcp

I have following structure in firebase data
Orders -> OrderID -> LocationHistory -> LocationHistoryID -> FieldsData
Orders and LocationHistory are constant whereas OrderID ,LocationHistoryID are document ID
I want to know if it is possible to generate a query to get all LocationHistory of an order in repository which extends FirestoreReactiveRepository
in rest it whould be /Orders/10002/LocationHistory/
Belwo is the code i am currently using
import org.springframework.cloud.gcp.data.firestore.Document;
import com.google.cloud.firestore.annotation.DocumentId;
import com.google.cloud.firestore.annotation.PropertyName;
import lombok.Getter;
import lombok.Setter;
#Setter
#Getter
#Document(collectionName = "Orders/10002/LocationHistory")
public class LocationHistory
{
#DocumentId
private String id;
private String lat;
#PropertyName("long")
private String longitude;
}

Since LocationHistory is a sub-collection of the Orders, you should retrieve the Order which will contain the LocationHistory.
#Setter
#Getter
#Document(collectionName = "Orders")
public class Order
{
#DocumentId
private String id;
private List<LocationHistory> locationHistory;
}
#Setter
#Getter
public class LocationHistory
{
#DocumentId
private String id;
private String lat;
#PropertyName("long")
private String longitude;
}

Related

Spring Boot JPA returns correct count but no data

Evening,
I have a Spring application that is connected to a PostgresSQL db. I can connect to the database and see that the query is returning the correct number of elements for the array but nothing in them:
curl http://localhost:8080/books
[{},{},{}]%
My Book model looks like this:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.math.BigDecimal;
#Entity
public class Book {
#Id
#GeneratedValue
private Long id;
private String name;
private String author;
private BigDecimal price;
public Book() {}
public Book(String name, String author, BigDecimal price) {
this.name = name;
this.author = author;
this.price = price;
}
}
and the controller:
#RestController
public class BookController {
#Autowired
private BookRepository repository;
// Find
#GetMapping("/books")
List<Book> findAll() {
List<Book> books = repository.findAll();
System.out.println(books);
return repository.findAll();
}
}
I've looked at these questions here, here and here but those answers didn't fit with this.
What am I not doing to see data come back?
In order for your entity to be serialized by Spring the entity needs to have getters for its properties. You could use lombok to auto-generate getter/setters for you entity properties or just write them your own.

No property .. found for type .. in spring boot

I'm a beginner with spring and I have this little issue. "No property questionId found for type CourseTestCompleteField!" I have 2 model classes that are connected via a one to one join.
That 2 model class are:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "questions")
public class CourseTestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="question_id")
private Long id;
#NotBlank
#Column(name = "question_course")
private String questionCourse;
#NotBlank
#Column(name = "question_type")
private String questionType;
public CourseTestQuestion(){
}
public CourseTestQuestion(String questionCourse, String questionType) {
this.questionCourse = questionCourse;
this.questionType = questionType;
}
// public getters and setters for all fields here
}
And:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "quiz_complete_field_questions",
uniqueConstraints = {
#UniqueConstraint(columnNames = "question_id")
}
)
public class CourseTestCompleteField {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "question_content")
private String questionContent;
#NotBlank
#Column(name = "answer")
private String answer;
#NotBlank
#Column(name = "points")
private String points;
#NotBlank
#Column(name = "course")
private String course;
#NotBlank
#Column(name = "teacher_username")
private String teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "question_id", referencedColumnName = "question_id")
private CourseTestQuestion courseTestQuestion;
public CourseTestCompleteField(){
}
public CourseTestCompleteField(CourseTestQuestion courseTestQuestion, String question, String answer, String points, String course, String teacher) {
this.courseTestQuestion = courseTestQuestion;
this.questionContent = question;
this.answer = answer;
this.points = points;
this.course = course;
this.teacher = teacher;
}
// public getters and setters for all fields here
}
My repo for both:
package com.example.springboot.repository;
import com.example.springboot.models.Course;
import com.example.springboot.models.CourseTestQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface CourseTestQuestionRepository extends JpaRepository<CourseTestQuestion, Long> {
Optional<CourseTestQuestion> findById(Long id);
Optional<CourseTestQuestion> findByQuestionCourse(String questionCourse);
}
And:
package com.example.springboot.repository;
import com.example.springboot.models.CourseTestCompleteField;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
#Repository
public interface CourseTestCompleteFieldRepository extends JpaRepository<CourseTestCompleteField, Long> {
Optional<CourseTestCompleteField> findById(Long id);
Optional<CourseTestCompleteField> findByQuestionId(Long questionId);
Optional<CourseTestCompleteField> findByCourse(String course);
List<CourseTestCompleteField> findByQuestionContent(String questionContent);
List<CourseTestCompleteField> findByTeacher(String teacher);
Boolean existsByQuestionContent(String questionContent);
}
The problem is with Optional<CourseTestCompleteField> findByQuestionId(Long questionId);but I don't get it why, because in database I have the table for CourseTestCompleteFieldModel with question_id column, and in CourseTestCompleteField I have CourseTestQuestion object. Tho, the table for CourseTestCompleteField has a different name, could be this a problem? I should rename the table to course_test_complete_field?
Can someone help me please? Thank you
Since,This is a query on nested Object. You need to update your query as this.
Optional<CourseTestCompleteField> findByCourseTestQuestion_Id(Long questionId);
This works even without "_"
Optional<CourseTestCompleteField> findByCourseTestQuestionId(Long questionId);
But better to put "_" while accessing nested fields for better readability.
There is no field call questionId in you entity and you have id only.
That's you got error. You can use that findyById(). That's only enough.
If you would like write JPA repository method like findBy..., getBy..., deleteBy...., countBy..., After this you need append exact field name from entity.
For example if you entity have name then can write below methods. findByName(); deleteByName(); countByName();
So try as below.
findBycourseTestQuestion(Object o);
Pass questions object.

Nested property not found in a Spring Data query method declaration

I'm trying to use findBy... in my repository to get a Savingaccount object passing a nested attribute(name) as a parameter. Currently I'm using:
Mono<SavingAccount> findByOwnerName(String name);
but I'm getting this error: No property name found for type Owner! Traversed path: SavingAccount.owner.
My repository:
package com...SavingAccMS.Repository;
import com.everis.SavingAccMS.Model.Owner;
import com.everis.SavingAccMS.Model.SavingAccount;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;
public interface SavingAccountRepo extends ReactiveMongoRepository<SavingAccount, String>
{
Mono<SavingAccount> findByNumber(String number);
//This one is the problem
Mono<SavingAccount> findByOwnerName(String name);
Mono<SavingAccount> findByOwner(Owner owner);
}
My Entity:
package com...SavingAccMS.Model;
import java.security.acl.Owner;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "SavingAccs")
public class SavingAccount
{
#Id
private String id;
#NotBlank
private String number;
#NotBlank
private Owner owner;
#NotBlank
private String currency;
#NotBlank
private double balance = 0.00;
#NotBlank
private String status;
}
package com...SavingAccMS.Model;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "Owners")
public class Owner
{
public String dni;
public String name; //findBy this attribute is required.
}
According to your imports, the Owner in your SavingAccount refers to java.security.acl.Owner, not the one you defined yourself in om...SavingAccMS.Model.Owner. The former does not carry a name attribute.
I'm not certain but I don't think you can find the owner name in hibernate like that.
I would try the following!
#Query("SELECT * FROM SavingAccount where owner.name = :name")
Mono<SavingAccount> findByOwnerName(#Param("name") String name);

Superclass Fields Using #Builder Lombok

WHow to fetch the Superclass fields in the builder?
Parent:
package com.goomo.sso.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
#AllArgsConstructor
#NoArgsConstructor
#Data
public class BaseResponseModel implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private StatusMessage statusMessage;
}
Child:
package com.goomo.sso.dto;
import java.io.Serializable;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
#Data
#EqualsAndHashCode(callSuper=false)
#ToString
public class UserRequest extends BaseResponseModel implements Serializable {
private static final long serialVersionUID = 1L;
private String clientName;
private String role;
private String groupName;
private String userName;
#Builder
public UserRequest(String status, StatusMessage statusMessage, String clientName, String role, String groupName,
String userName) {
super(status,statusMessage);
this.clientName = clientName;
this.role=role;
this.groupName=groupName;
this.userName = userName;
}
}
I couldn't get the fields of the parent class in the builder. Can you please suggest me the correct way of achieving it?

How to pull an alias from native query in JPA

I'm trying to pull an alias from native query in JPA, something like (SUM,COUNT), Well the method can return an integer if i pulled SUM or COUNT perfectly (ONLY if i pulled it alone) .
but how can i pull it with the rest of object? here is a sample what i am trying to do
#Entity
#Table("hotels")
public class Hotel {
#Column(name="id")
#Id
private int hotelId;
#Column(name="hotel_name")
private String hotelName;
#OneToMany
private List<Availability>list;
private int avaialbeCount; //this one should be Aliased and need to be pulled by none column
}
Repository
public interface HotelRepository extends JpaRepository<Hotel,Integer>{
#Query(value="select h.*,a.count(1) as avaialbeCount from hotels h INNER JOIN availability a on (a.hotel_id=h.hotel_id) group by a.date",nativeQuery=true)
public List<Hotel> getHotels();
}
in the above repository. im trying to get avaialbeCount with hotel columns but im unable to pull it, however i can pull it by removing the select h.* and keep select COUNT only and make the method returns Integer instead of Hotel
You can use JPQL, something like this
#Query("SELECT new test.Hotel(h.hotelName, count(h)) FROM Hotel h GROUP BY h.hotelName")
to use this new test.Hotel(h.hotelName, count(h)) construction, you need constructor like
public Hotel(String hotelName, Long avaialbeCount) {
this.hotelName = hotelName;
this.avaialbeCount = avaialbeCount;
}
Example:
Repository:
package test;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface HotelRepo extends JpaRepository<Hotel, Long> {
#Query("SELECT new test.Hotel(h.hotelName, count(h)) FROM Hotel h GROUP BY h.hotelName")
List<Hotel> getHotelsGroupByName();
}
Entity:
package test;
import javax.persistence.*;
#Entity
#Table(name = "hotels")
public class Hotel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long hotelId;
#Column(name = "hotel_name")
private String hotelName;
#Transient
private Long avaialbeCount;
public Hotel() {
}
public Hotel(String hotelName) {
this.hotelName = hotelName;
}
public Hotel(String hotelName, Long avaialbeCount) {
this.hotelName = hotelName;
this.avaialbeCount = avaialbeCount;
}
#Override
public String toString() {
return "Hotel{" +
"hotelId=" + hotelId +
", hotelName='" + hotelName + '\'' +
", avaialbeCount=" + avaialbeCount +
'}';
}
}
#Transient annotation is used to indicate that a field is not to be persisted in the database.

Resources