Can not map native sql result into dto using #Query annotation - spring

I have followed JPA interface projection process to map native SQL result into a custom DTO but still, I am getting result in AbstractJpaQuery$TupleConverter$TupleBackedMap format. How can I map the result into desired DTO class?
This is the repository class
#Repository
public interface SubjectMarkingCriteriaRepository extends JpaRepository<SubjectMarkingCriteria,Long> {
#Query(
value = "select smc.id as id ,c.class as academicClass,s.subject as subject,mc.criteria as criteria " +
"from subject_marking_criteria smc " +
"join subject s on smc.subject_id = s.id " +
"join marking_criteria mc on smc.marking_criteria_id = mc.id " +
"Join class c on s.class_id = c.id ",
nativeQuery = true)
List<ResultDTO> findAllByParam();
}
DTO interface
public interface ResultDTO{
Long getId();
String getAcademicClass();
String getSubject();
String getCriteria();
}
Entities are :
#Data
#Entity
#Table(name = "subject_marking_criteria")
public class SubjectMarkingCriteria {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="subject_id")
private Long subjectId;
#Column(name="marking_criteria_id")
private Long markingCriteriaId;
}
#Data
#Entity
#Table(name = "subject")
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="subject")
private String subject;
#Column(name="bn_subject")
private String bnSubject;
}
#Data
#Entity
#Table(name = "marking_criteria")
public class MarkingCriteria {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="criteria")
private String criteria;
#Column(name="bn_criteria")
private String bnCriteria;
}
Result found as below
results = {ArrayList#12758} size = 2
0 = {$Proxy210#12766} "org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap#1c56a65c"
1 = {$Proxy210#12767} "org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap#31c7eaa"

Related

Spring Boot JPA Using Many-to-Many relationship with additional attributes in the join table

I have two simple classes Student and Course. I am trying to set up many to many relationship between these classes. I want to use additional table whose PRIMARY KEY is the combination of the primary keys of student and course tables (student_id and course_id).
The student class:
#Entity
#Table(name = "student")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "surname")
private String surname;
#OneToMany(mappedBy = "student")
private Set<CourseStudent> courses;
}
The course class:
#Entity
#Table(name = "course")
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String courseName;
#OneToMany(mappedBy = "course")
Set<CourseStudent> students;
}
The entity that stores the relationship between course and the student:
#Entity
#NoArgsConstructor
#Data
public class CourseStudent {
#EmbeddedId
CourseStudentKey id;
#ManyToOne
#MapsId("studentId")
#JoinColumn(name = "student_id")
Student student;
#ManyToOne
#MapsId("courseId")
#JoinColumn(name = "course_id")
Course course;
public CourseStudent(Student student, Course course) {
this.student = student;
this.course = course;
this.rating = 0;
}
int rating;
}
Attention: Since I want to have additional features in this entity (for example, storing the rating of the students for courses), I don't want to use #JoinTable idea that we implement in the Student class.
Since I have multiple attributes in the primary key of CourseStudent entity, I used the following class
#Embeddable
#Data
public class CourseStudentKey implements Serializable {
#Column(name = "student_id")
Long studentId;
#Column(name = "course_id")
Long courseId;
}
I have the following POST request to insert the student into a course:
#PostMapping("/insert/students/{studentId}/courses/{courseId}")
public CourseStudent insertStudentIntoCourse(#PathVariable(value = "studentId") Long studentId,
#PathVariable(value = "courseId") Long courseId) {
if (!studentRepository.existsById(studentId)) {
throw new ResourceNotFoundException("Student id " + studentId + " not found");
}
if (!courseRepository.existsById(courseId)) {
throw new ResourceNotFoundException("Course id " + courseId + " not found");
}
CourseStudent courseStudent = new CourseStudent(
studentRepository.findById(studentId).get(),
courseRepository.findById(courseId).get()
);
return courseStudentRepository.save(courseStudent);
}
I have manually added Student and the Course into my local database and send this request by using Postman.
http://localhost:8080/insert/students/1/courses/1
However, I get the following error:
{
"timestamp": "2022-08-04T12:33:18.547+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/insert/students/1/courses/1"
}
In the console, I get NullPointerException. What is the thing I am doing wrong here?

HOW JOIN two tables JPQL

How create a join pageable USING JPQL in Class Movie with MovieLanguage?
The Class Movie as a relationship 1 to 1 with MovieLanguage.
Movie:
Entity
#Table(name = "tb_movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private Double score;
private Integer count;
private String image;
public Movie() {}
public Movie(Long id, String title, Double score, Integer count, String image) {
this.id = id;
this.title = title;
this.score = score;
this.count = count;
this.image = image;
}
#OneToOne(cascade = CascadeType.ALL, mappedBy = "movie")
#JsonManagedReference
MovieLanguage movieLanguage;
/* getter and setter */
}
MovieLanguage:
#Entity
#Table(name = "tb_movie_language")
public class MovieLanguage {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String titleBrazil;
private String titleSpanish;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "movie_id")
#JsonBackReference
private Movie movie;
public MovieLanguage(){}
/* getter and setter */
}
Here is a JPQL example in MovieJoinRepository, but not working:
MovieJoinRepository:
public interface MovieJoinRepository extends JpaRepository<Movie, Long> {
#Query("SELECT obj FROM Movie obj INNER JOIN obj.movie_language mm WHERE obj.id = mm.id ")
Page<String> findAllPaged(Pageable pageable);
}
Thank you for you help!

Get data from multiple tables using one Mapping Table in Spring Boot

Procedure.java
#Entity
#Table(name = "procedures")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Procedure implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ProcedureId")
private int id;
#Column(name = "ProcedureName")
private String name;
#Column(name = "ProcedureCode")
private String code;
#Column(name = "ProcedureDesc")
private String desc;
// getters and setters
}
CPTClinicianDescriptor
#Entity
#Table(name = "cliniciandescriptor")
public class CPTClinicianDescriptor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int id;
#Column(name = "ConceptId")
private int conceptId;
#Column(name = "CPTCode")
private String cptCode;
#Column(name = "ClinicianDescriptorId")
private int clinicianDescriptorId;
#Column(name = "ClinicianDescriptor")
private String clinicianDescriptor;
// getters and setters
}
CPTProcedures
#Entity
#Table(name = "cptprocedures")
public class CPTProcedures {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int Id;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "ProcedureId")
private Procedure procedure;
#Transient
private int procedureId;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "CPTCodeSet")
private CPTClinicianDescriptor cptClinicianDescriptor;
#Transient
private int cptCodeSet;
// getters and setters
}
Here I have 3 table in mySql in those 2 are different separate tables, I created one table for Mapping that has foreign keys of Procedures and CPT when i get a list using Procedure It should get corresponding cpt data also.
ServiceImpl Like:
public List<Procedure> getCombinedProcedureList(int id) {
// TODO Auto-generated method stub
List<Procedure> pList = new ArrayList<Procedure>();
Procedure procedureList = procedureRepository.findCombById(id);
pList.add(procedureList);
return pList;
}
When i use
Repository like
#Query(value = "SELECT * FROM procedures JOIN cliniciandescriptor ON cliniciandescriptor.Id = ?1",nativeQuery = true)
Procedure findCombById(int id);
this query in Procedures Repository it is getting only procedures. So, what can i do to get the combined(joined) list of 2(procedures & CPT) tables using 3rd mapping table.

QuerySyntaxException in Spring Data JPA custom query

I have a Entity:
#Entity
#Table(name = "story", schema = "")
#Data
public class Story implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sID", unique = true, nullable = false)
private Long sID;
#Column(name = "vnName", nullable = false)
private String vnName;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd-MM-yyyy HH:mm:ss")
#Column(name = "sUpdate", length = 19)
private Date sUpdate;
}
And:
#Entity
#Table(name = "chapter", schema = "")
#Data
public class Chapter implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "chID", unique = true, nullable = false)
private Long chID;
#Column(name = "chName", nullable = false)
private String chName;
#JoinColumn(name = "sID", referencedColumnName = "sID")
#ManyToOne(fetch = FetchType.LAZY)
private Story story;
}
I had created custom pojo to get the latest update story with the latest chapter:
#Data
public class NewStory{
private Story story;
private Chapter chapter;
}
but when I get list :
#Repository
public interface StoryRepository extends CrudRepository<Story, Long> {
#Query(value="SELECT NEW com.apt.truyenmvc.entity.NewStory(s as newstory, c as newchapter)"
+ " FROM story s LEFT JOIN (SELECT * FROM Chapter c INNER JOIN "
+ " (SELECT MAX(c.chID) AS chapterID FROM Story s LEFT JOIN Chapter c ON s.sID = c.sID GROUP BY s.sID) d"
+ " ON c.chID = d.chapterID) c ON s.sID = c.sID order by s.sUpdate desc")
public List<NewStory> getTopView();
}
Error:
Warning error: org.hibernate.hql.internal.ast.QuerySyntaxException: story is not mapped.
Who could help me fix it? Or could it be done in a different way?
The error is pretty self explainatory. And its just a typo in your query. You are using story. And obviously thats not mapped as an Entity.
Fix it to Story

Caused by: java.sql.SQLSyntaxErrorException: [SQL0205] Column MITMAS_MMCONO not in table OOLINE in schema

I have 3 entity classes
Ooline:
#Entity
#IdClass(OolineId.class)
#NamedQuery(name="Ooline.findAll", query="SELECT o FROM Ooline o")
public class Ooline implements Serializable
{
private static final long serialVersionUID = 1L;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="mitmas_mmcono" , referencedColumnName="mmcono"),
#JoinColumn(name="mitmas_mmitno" , referencedColumnName="mmitno")
})
private Mitmas mitmas ;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="mitfac_m9cono", referencedColumnName="m9cono"),
#JoinColumn(name="mitfac_m9itno", referencedColumnName="m9itno"),
#JoinColumn(name="mitfac_m9faci", referencedColumnName="m9faci")
})
private Mitfac mitfac ;
#Id
private String obitno;
#Id
private BigDecimal obcono;
#Id
private String obfaci;
private BigDecimal obabno;
//getter and setters
}
Mitfac:
#Entity
#IdClass(MitfacId.class)
#NamedQuery(name="Mitfac.findAll", query="SELECT m FROM Mitfac m")
public class Mitfac implements Serializable
{
private static final long serialVersionUID = 1L;
#OneToMany(mappedBy="mitfac",fetch=FetchType.LAZY)
private List<Ooline> oolineItem;
#Id
private String m9itno;
#Id
private String m9faci;
#Id
private BigDecimal m9cono;
private String m9acrf;
private BigDecimal m9appr;
//getter and setter
}
Mitmas:
#Entity
#IdClass(MitmasId.class)
#NamedQuery(name="Mitmas.findAll", query="SELECT m FROM Mitmas m")
public class Mitmas implements Serializable
{
private static final long serialVersionUID = 1L;
#OneToMany(mappedBy="mitmas",fetch=FetchType.LAZY)
private List<Ooline> ooline;
#Id
private String mmitno;
#Id
private BigDecimal mmcono;
private BigDecimal mmaad0;
private BigDecimal mmaad1;
private String mmaccg;
//getter and setter methods
}
And following is my Repository file:
public interface OolineRepository extends JpaRepository<Ooline, String>
{
public static final String ORDER_LINE_QUERY =
"select x.obcono,x.oborno,x.obponr, x.obposx, x.obfaci, x.obitno, x.obitds, x.oborqt, "
+ "x.oborqa, x.obwhlo, x.obadid, x.obpopn, x.obrout, x.obmodl, x.oborst,"
+ " x.obnepr, x.obdwdz, x.obcodz, x.obpldt, x.obplhm,"
+ " x.obprrf, x.obspun, x.obrgdt, x.obrgtm, x.obwhsl from Ooline x "
+ "left join x.mitmas y left join x.mitfac z "
+ "where x.obcono = :cono and x.oborno = :orno";
#Query(ORDER_LINE_QUERY)
public List<Ooline> getOolineLines(#Param("cono") BigDecimal cono, #Param("orno") String orno);
}
I am supposed to execute following query in SQL
"select x.oborno,x.obponr, x.obposx, x.obfaci, x.obitno, x.obitds, x.oborqt, x.oborqa,
x.obwhlo, x.obadid, x.obpopn, x.obrout, x.obmodl,x.oborst, x.obnepr, x.obdwdz, x.obcodz,
x.obpldt, x.obplhm,x.obprrf, x.obspun, x.obrgdt, x.obrgtm, x.obwhsl from Ooline x join
schema.mitmas on mmcono = obcono and mmitno = obitno left join schema.mitfac on
m9cono = obcono and m9faci = obfaci and m9itno = obitno where obcono =1 and oborno = 'asasa'";
Can anyone verify if have constructed and mapped entity correctly .
But query is not constructing the way I am expecting .Getting an error "Column MITMAS_MMCONO not in table OOLINE ." Can anyone help me in this
The mapped entity is correct constructed, but the query is not prpeely defined. You want a left join from child enity Ooline to master entity Mitmas, and it tries to do that by joining on the primary key fields from Ooline to those from Mitmas (see generated sql) which is not correct. Why do you want a left join since you are not actually using anything from the master entity?
I have changed as following
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(updatable=false,insertable=false,name="obcono",referencedColumnName="mmcono"),
#JoinColumn(updatable=false,insertable=false,name="obitno",referencedColumnName="mmitno")
})
private Mitmas mitmas ;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(updatable=false,insertable=false,name="obcono",referencedColumnName="m9cono"),
#JoinColumn(updatable=false,insertable=false,name="obitno",referencedColumnName="m9itno"),
#JoinColumn(updatable=false,insertable=false,name="obfaci",referencedColumnName="m9faci")
})
private Mitfac mitfac ;

Resources