How to fetch data from multiple tables and put into an custom object? spring boot? - spring-boot

JpaRepository
public interface SessionsStoreRepository extends JpaRepository<SessionsStore, Integer> {
SessionsStore findBySessionId(String sessionId);
//JPQL
#Query(value = "SELECT s.username,s.loginTime,s.logoutTime, e.firstName, e.lastName from SessionsStore s, Employee e "
+ " where e.username = s.username and s.isActive= 1")
List<ActiveSession> findUsers();
}
ActiveSession
import java.time.LocalDateTime;
import lombok.Data;
#Data
public class ActiveSession {
private String username;
private String firstName;
private String lastName;
private LocalDateTime loginTime;
private LocalDateTime logoutTime;
}
How can I store the data fetch by #Query(...) in ActiveSession Object Or is there any other way? I tried storing data into object (i.e List<Object>) but I'm using ftl for view and it does not allow you fetch the data unless the object have getters.

you can use a class-based projection to achive this.
More information here, or there is a good example of how to use it here

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.

Lazy Load in Hibernate

I can not make Lazy Load work on Spring.
#Entity
public class Livro {
#JsonInclude(Include.NON_NULL)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotEmpty(message = "Campo nome é obrigatorio")
private String nome;
#JsonInclude(Include.NON_NULL)
#JsonFormat(pattern = "dd/mm/yyy")
#NotNull(message = "Campo publicacao é obrigatorio")
private Date publicacao;
#JsonInclude(Include.NON_NULL)
private String editora;
#JsonInclude(Include.NON_NULL)
private String resumo;
#OneToMany( mappedBy = "livro", fetch = FetchType.LAZY )
private List<Comentario> comentarios;
//Comentario.Java
#Entity
public class Comentario {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JsonProperty("comentario")
private String texto;
private String usuario;
#JsonFormat(pattern = "dd/mm/yyy")
private Date data;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "LIVRO_ID")
#JsonIgnore
private Livro livro;
//LivrosRepository.java
package com.curso.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.curso.domain.Livro;
public interface LivrosRepository extends JpaRepository<Livro, Long> {
}
//ComentariosRepository.java
package com.curso.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.curso.domain.Comentario;
public interface ComentariosRepository extends JpaRepository<Comentario, Long> {
}
//LivrosService.java
#Service
public class LivrosService {
#Autowired
private LivrosRepository livrosRepository;
#Autowired
private ComentariosRepository comentariosRepository;
// [...]
public List<Livro> listar() {
return livrosRepository.findAll();
}
}
When I make a request to list the books, the behavior I expect is that I list all the data in books, but without the comments, since I'm using the java annotation
fetch = FetchType.LAZY, but the behavior I have is the return of all the data in the workbook.
[
{
"id": 4,
"nome": "Teste2",
"publicacao": "01/01/2018",
"editora": "Polenta",
"comentarios": [
{
"id": 1,
"usuario": "tester",
"data": "26/03/2019",
"comentario": "Comentario 1"
}
]
}
]
Hibernate Session exists within method with #Transactional. Passing entity outside Service class is a bad practise because session is being closed after leaving your listar method. On the other hand your entity contains lazy initialised collections (List<Comentario> comentarios), which cannot be pulled once session is closed.
The good practise is to map entity onto transport object and return those transport objects from service (not raw entities).
First of all you should wrap your public List<Livro> listar() method with #Transactional. Hibernate Session will be alive during execution of this method. It means you can pull lazy initialized elements within this method.
Secondly you should define LivroDto class with all necessary fields and map your Livro entity onto this POJO within this method then return LivroDro from the service.

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.

How to write custom query in Mongo Spring Data JPA

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
#Repository
public interface PersonRepository extends MongoRepository<Person, String> {
#Query("{ 'firstname' : ?0 }")
List<Person> findByFirstname(String firstname);
}
I am using spring data jpa with MongoDB. I am able to save, delete or retrieve (all records) using repository.
I am trying to retrieve record based on a property value. (Custom Query shown above). This does not work.
Can someone help me in finding out how to write custom Queries in MongoRepository where I can pass a column value and get the matching rows.
EDIT:
Adding Code.
#Document/*(collection = "person")*/
public class Person {
#Id
private String id;
private String firstName;
private String lastName;
private Address address;
// gettters and setters
}
#Service
public class PersonServiceImpl{
#Autowired
private PersonRepository personRepository;
public Person findPersonByFirstName(String firstName) {
List<Person> person = personRepository.findAllByFirstName(firstName);
System.out.println("** Data Retrieved **" );
return person.get(0);
}
}
You don't need a custom query for this kind of query.
Following should just work (provided your field in Person class is "firstname" - is that righ?)
List<Person> findAllByFirstname(String firstname);
Does your query work from a mongo console?

Resources