SQL query to JPA specification - sql

I have this simplified JPA entities
#Entity
#Table(name = "students")
public class Student {
#Id
private Integer id;
private String name;
//getters, setters
}
#Entity
#Table(name = "averages")
public class Averages {
#Id
private Integer id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "student_id", referencedColumnName = "id")
private Student student;
private float value;
//getters, setters
}
How I can write this query using JPA Specification and CriteriaBuilder?
SELECT students.id
FROM students,
averages
WHERE averages.student_id = students.id
GROUP BY students.id
HAVING AVG(averages.value) > 6

It should be something like:
select student.id
from Averages average
join average.student student
group by student.id
having avg(average.value)>6
i have no way of testing this
Edit: this is using EntityManager#createQuery(String)

Related

Foreign key constraint violation when deleting audited Hibernate envers Entity

I have a situation that looks like the following :
Two entities Employee and EmployeeHty :
#Entity
#Table(name = "employee")
#Audited
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Employee {
#Id
#GeneratedValue
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "employee_id")
private Employee employee;
}
#Entity
#Table(name = "employee_hty")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class EmployeeHty {
#EmbeddedId
private HtyCompositePrimaryKey htyCompositePrimaryKey;
#Column(name = "revision_type")
private Integer revisionType;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "employee_id")
private Employee employee;
}
#Embeddable
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
public class HtyCompositePrimaryKey implements Serializable {
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name = "revision_id")
private EmployeeAuditRevision auditRevision;
}
#Entity
#Table(name = "employee_audit_revision")
#Data
#AllArgsConstructor
#NoArgsConstructor
#RevisionEntity(EmployeeRevisionListener.class)
public class EmployeeAuditRevision {
#Id
#GeneratedValue
#RevisionNumber
#Column
private Long revisionId;
#RevisionTimestamp
#Column
private Date revisionDate;
#Column
private String userUid;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
}
An employee could have himself as boss. So i end up with this values in my database :
employee
id
name
employee_id
1
Jack
1
2
Melanie
null
employee_hty
id
revision_id
revision_type
name
employee_id
1
102
0
Jack
1
2
103
0
Melanie
null
revision types :
0 : created
1: updated
2: deleted
I want to delete manually Jack from the employee table and add a delete revision using SQL
INSERT INTO employee_hty VALUES (1, 104, 2, Jack, 1);
DELETE FROM employee WHERE id = 1;
Here is the situation i would like to be in :
employee
id
name
employee_id
2
Melanie
null
employee_hty
id
revision_id
revision_type
name
employee_id
1
104
2
Jack
1
1
102
0
Jack
1
2
103
0
Melanie
null
But since employee_hty has a foreign key constraint that link the column employee_id(table employee_hty) to the column id(table employee) it is not possible to do this. And i would like to have your thoughts on the matter.
Is deleting the foreign key constraint could be the solution ?
*NB: some details were omitted for the purpose of simplicity. *
Either remove the constraint or don’t populate the column for deletes

How to make JPA JOIN query list giving only one item instead of all items by condition

I have some Entities looks like this. Very abstract:
#Entity
class Man {
#Id
String name;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "name", cascade = CascadeType.ALL)
List<Car> carList;
}
#IdClass(TypeId.class)
#Entity
class Car {
#Id
#NonNull
String name;
#Id
#NonNull
String class;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "class",
referencedColumnName = "class",
insertable = false,
updatable = false)
Engine engine;
}
#Entity
class Engine() {
#Id
#NonNull
String class;
String type;
Integer count;
}
class TypeId {
String name;
String class;
}
I need to construct #Query - select MAN with condition: if Engine types are equals, I need to take one Car with less Engine count. And return Man with only one Car if condition is met. Otherwise return Man with all cars.

ORM: EclipseLink AssociationOverride "Persistent type of override attribute cannot be resolved"

I am building an application that has a database of students, courses, and it also keeps track of all the courses that each student is taking,
I have an entity for Course and Student, and they have a one to many relationship with entity StudentCourses and an embeddable class of StudentCoursesID.
In the StudentCourse when I try to use the annotation AssociationOverride it gives me a problem saying
"Persistent type of override attribute "student" cannot be resolved"
"Persistent type of override attribute "course" cannot be resolved"
and
"Embedded ID class should not contain relationship mappings"
I dont understand if i did the mapping wrong or if there is a disconnection between my entities and classes.
Below I have each of the the entity starting with StudentCourses which is giving me issues.
StudentCourses
package jpa.entitymodels;
import javax.persistence.*;
#Entity
#Table(name = "student_courses")
#AssociationOverrides({
#AssociationOverride(name = "student", joinColumns = #JoinColumn(name = "sEmail")),
#AssociationOverride(name = "course", joinColumns = #JoinColumn(name = "cId"))
})
public class StudentCourses {
private StudentCoursesId id = new StudentCoursesId();
public StudentCourses() {
}
public StudentCourses(StudentCoursesId id) {
this.id = id;
}
#EmbeddedId
public StudentCoursesId getId() {
return id;
}
StudentCoursesId
package jpa.entitymodels;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;
import java.io.Serializable;
#Embeddable
public class StudentCoursesId implements Serializable {
private static final long serialVersionUID = 1L;
private Student student;
private Course course;
public StudentCoursesId() {
}
#ManyToOne
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
#ManyToOne
public Course getCourse() {
return course;
}
Course
package jpa.entitymodels;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "course")
public class Course {
#Id
#Column(name = "id")
int cId;
#Column(name = "name")
String cName;
#Column(name = "instructor")
String cInstructorName;
#OneToMany(mappedBy = "id.course", fetch = FetchType.LAZY)
List<StudentCourses> studentCourses = new ArrayList<>();
Student
package jpa.entitymodels;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
#Entity
#Table(name="student")
public class Student {
#Id
#Column(name = "email")
String sEmail;
#Column(name = "name")
String sName;
#Column(name = "password")
String sPass;
#OneToMany(mappedBy = "id.student", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<StudentCourses> studentCourses = new ArrayList<>();
The 'student' doesn't exist in StudentCourses which is why you get the error. Overrides you want to apply to the embeddable need to be defined on the embeddable mapping, not the StudentCourses class.
#Entity
#Table(name = "student_courses")
public class StudentCourses {
#Embedded
#AttributesOverride({
#AttributeOverride(name = "student", joinColumns = #JoinColumn(name = "sEmail")),
#AttributeOverride(nname = "course", joinColumns = #JoinColumn(name = "cId"))})
private EmbeddableClass embeddableClass;
public StudentCourses() {
}
}
JPA requires an ID class that has the simple pk types within it (or other nested composite PK classes, not relationships), requiring StudentCoursesId have a int/string property for the cId and sEmail. If you want to have mappings to course/student, maybe see the mapsId annotation or alternatively, I would map it like this:
#Entity
#Table(name = "student_courses")
#IdClass(StudentCoursesId.class)
public class StudentCourses {
#Id
#JoinColumn(name = "sEmail")
Student student;
#Id
#JoinColumn(name = "cId")
Course course;
}
public class StudentCoursesId implements Serializable {
private static final long serialVersionUID = 1L;
private String student;//Name matches id property in StudentCourses
private int course;
}

JPA Query mapping

I want to use orderNumber in ProductRepository but I keep getting SQL error. I mapped both sides.
this is product entity.
#Entity
public class Product extends BaseEntity {
#Id
#GeneratedValue
#Column(name = "product_id")
private Long id;
#ManyToOne
#JoinColumn(name = "orderItem_id")
private OrderItem orderItem;
this is orderItem entity.
#Entity
public class OrderItem extends BaseEntity {
#Id
#GeneratedValue
#Column(name = "orderItem_id")
private Long id;
private String orderNumber
#OneToMany(mappedBy = "orderItem", cascade = CascadeType.ALL, orphanRemoval = true)
#Builder.Default
private List<Product> products = new ArrayList<Product>();
this is query in ProductRepository.
#Query(value = "SELECT * FROM OrderItem a, Product b WHERE a.orderItem_id = b.orderItem_id", nativeQuery = true)
Product findByOrderNumber(String orderNumber);
Alternatively, you can try query by a method as shown below, you don't need to use the #Query in this case.
ProductRepository
Product findByOrderItemOrderNumber(String orderNumber);
you can find more details here

How to implement bidirectional hibernate relationship correctly?

#Entity
#Table(name = "project")
public class Project {
#Id
#Column(name = "project_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#OneToOne
#JoinColumn(name = "idea_id", referencedColumnName = "idea_id")
#JsonIgnore
private Idea idea; .......}
And
#Entity
#Table(name = "idea")
public class Idea {
#Id
#Column(name = "idea_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Size(max = 240)
#NotNull
private String description;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "project_id", referencedColumnName = "project_id")
private Project project; ..........}
What is wrong with my hibernate relationships in these two classes? This is example of relationship that I want to implement.
And this is actual tables that I get with these relationships:
Idea table:
And Project table:
How to get rid of null values in idea_id column in project table?