Create entity using join in jpa hibernate - java

I'm stuck with a problem in Java, hibernate (jpa)
So, I have 2 classes: Class and Classroom, each one being entities
#Entity
#Table(name = "CLASSES")
public class Class {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="ID")
private Long id;
#Column(name = "TEACHER_ID")
private Long teacherId;
#Column(name = "NAME")
private String name;
#Column(name = "YEAR")
private Integer year;
#Column(name = "SECTION")
private String section;
}
#Entity
#Table(name = "CLASSROOMS")
public class Classroom {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "LOCATION")
private String location;
#Column(name = "CAPACITY")
private Integer capacity;
}
Also, I have another java class called Planner which connect these two classes (their tables - using classroom_id and class_id); I have a table for this Planner
#Entity
#Table(name = "PLANNERS")
public class Planner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#Column(name = "CLASSROOM_ID")
private Long classroomId;
#Column(name = "CLASS_ID")
private Long classId;
#Column(name = "STARTTIME")
private Time startTime;
#Column(name = "ENDTIME")
private Time endTime;
#Column(name = "DATA")
private Date date;
}
What I need: a new entity (or just output data) which will include all fields from PLANNERS, field NAME from CLASSES and field NAME from CLASSROOMS.
In SQL, this query is:
select M.classroom_id, M.class_id, M.starttime, M.endtime, M.data, CL.NAME AS "ROOM NAME (FROM CLASSROOMS)", C.NAME AS "COURSE NAME (FROM CLASSES)" FROM PLANNERS M INNER JOIN CLASSROOMS CL ON CL.ID = M.CLASSROOM_ID INNER JOIN CLASSES C ON C.ID = M.CLASS_ID
(inner join using classroom_id and class_id)
How can I do this on hibernate jpa? I want to get the objects (rows) returned by the above query.
I searched a lot, I find about join column, other annotations (e.g. OneToMany etc) but I didn't succeed, so I need help

Related

JPA : How to handle mapping with a table that has relationship with two other tables?

I have three tables, table A (product), table B (invoice) and table C (invoices_info) which contains two columns referencing invoice_id and product_id. How can i insert a new entry (a new invoice) while inserting the products to the appropriate table and inserting the invoice info to its table also ?
Here are the entity classes :
Product
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "family_id")
private long familyId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_category")
private String productCategory;
#Column(name = "product_quantity")
private int productQuantity;
//getters and setters
}
Invoice
#Entity
#Table(name = "invoice")
public class Invoice {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "invoice_id")
private Long id;
#Column(name = "provider_id")
private Long providerId;
#Column(name = "total")
private int invoiceTotal;
#Column(name = "date")
private Date invoiceDate;
//getters and setters
}
InvoiceInfo
#Entity
#Table(name = "invoice_info")
public class InvoiceInfo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "item_id")
private long id;
#Column(name = "product_id")
private long productId;
#Column(name = "invoice_id")
private long invoiceId;
//getters and setters
}
InvoiceInfo should be join table, Define relationship on entities Product & Invoice using annotations #OneToMany, #ManyToOne based on your requirement.
You have to create relationships between your entities by using a set of annotations like: #ManyToOne, #OneToMany, #ManyToMany or #OneToOne... and other annotations if needed.
In your case I am not really sure you need an InvoiceInfo table, as the Invoice table can (or should) already contains the list of products.
I would suggest you the following relationships:
Product
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "family_id")
private long familyId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_category")
private String productCategory;
#Column(name = "product_quantity")
private int productQuantity;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "invoice_id", referencedColumnName = "id")
private Invoice invoice;
//getters and setters
}
Invoice
#Entity
#Table(name = "invoice")
public class Invoice {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "invoice_id")
private Long id;
#Column(name = "provider_id")
private Long providerId;
#Column(name = "total")
private int invoiceTotal;
#Column(name = "date")
private Date invoiceDate;
#OneToMany(mappedBy = "product")
private List<Product> products;
//getters and setters
}
As your table InvoiceInfo no longer exists, you just have to insert you data in two table like this:
Invoice invoice = invoiceRepository.save(invoice);
Product product = new Product();
// Set the other properties
product.setInvoice(invoice);
productRepository.save(product);

How get 2 SELECT in 1 query with SPRING DATA

I have 3 entities :
#Entity
#Table(name = "copy")
public class Copy {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "format")
private String format;
#Column(name = "status")
private String status;
#ManyToOne
#JoinColumn(name = "book_id")
private Book book;
#ManyToOne
#JoinColumn(name = "library_id")
private Library library;
#Entity
#Table(name = "book")
public class Book implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "title")
private String title;
#Column(name = "pub_date")
private Date pubDate;
#Column(name = "page")
private int page;
#Column(name = "synopsis")
private String synopsis;
//TODO Image à gérer
#Column(name = "cover")
private String cover;
#ManyToOne
#JoinColumn(name = "categorie_id")
private Categorie categorie;
#ManyToOne
#JoinColumn(name = "author_id")
private Author author;
#OneToMany(mappedBy = "book")
List<Copy> copyList = new ArrayList<>();
#Entity
#Table(name = "library")
public class Library implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "nom")
private String nom;
#Column(name = "adress")
private String adress;
#Column(name = "phone_num")
private String phoneNum;
#Column(name = "email")
private String email;
#OneToMany(mappedBy = "library")
private List<Copy> copyList = new ArrayList<>();
I would like to recover the number of copies of a book according to its format and its libraries. However I cannot figure out how to retrieve a list of copies and the total number depending on the format and its library. How can I do. I wrote this request but I can't get what I want.
My request :
#Query("SELECT DISTINCT c, COUNT(c.format) FROM Copy c WHERE c.book.id = :id")
List<Copy> getCopyById(#Param("id") Long id);
first you need to create class to handel query result (copy,total)
public class CopyWithTotal{
Copy c;
int total;
CopyWithTotal(Copy c, int total){
this.c = c;
this.total = total;
}
}
then you should constratc this class in the query
#Query("SELECT new packgeTo.CopyWithTotal(DISTINCT c, COUNT(c.format)) FROM Copy c WHERE c.book.id = :id group by c")
List<CopyWithTotal> getCopyById(#Param("id") Long id);
whenever you use aggregation function like count all selected column shoud apper in the group by

How to maintain foreign key relationship in hibernate

I have two classes and I want to have a one to many relation between them, for e.g.:
Home(id<int>, rooms<string>)
Vehicle(id<int>, home_id<int>, name<string>)
I need to have a relation between Home and Vehicle class using Home.id and vehicle.home_id.
Please suggest any example which I can use here for CURD operation to implement REST service.
I need to have a relation between Home and Vehicle class using Home.id
and vehicle.home_id.
Your entities should look like this :
Vehicle Entity
#Entity
#Table(name = "vehicle", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Vehicle implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "name")
private String name;
#JoinColumn(name = "home_id", referencedColumnName = "id")
#ManyToOne
private Home homeId;
//constructor getter & setters
}
Home Entity
#Entity
#Table(name = "home", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Home implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "room")
private Character room;
#OneToMany(mappedBy = "homeId")
private List<Vehicle> vehicleList;
//constructor getter & setters
}

How can I convert this 3 JOIN query into a Spring Data JPA named query method?

I am not so into Spring Data JPA and I have the following problem trying to implement a named query (the query defined by the method name).
I have these 3 entity classes:
#Entity
#Table(name = "room_tipology")
public class RoomTipology implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "tipology_name")
private String name;
#Column(name = "tipology_description")
private String description;
#Column(name = "time_stamp")
private Date timeStamp;
#OneToMany(mappedBy = "roomTipology")
private List<Room> rooms;
#OneToOne(mappedBy = "roomTipology")
private RoomRate roomRate;
// GETTER AND SETTER METHODS
}
That represents a tipology of room and that contains this field
#OneToMany(mappedBy = "roomTipology")
private List<Room> rooms;
So it contains the list of room associated to a specific room tipology, so I have this Room entity class:
#Entity
#Table(name = "room")
public class Room implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name = "id_accomodation_fk", nullable = false)
private Accomodation accomodation;
#ManyToOne
#JoinColumn(name = "id_room_tipology_fk", nullable = false)
private RoomTipology roomTipology;
#Column(name = "room_number")
private String number;
#Column(name = "room_name")
private String name;
#Column(name = "room_description")
#Type(type="text")
private String description;
#Column(name = "max_people")
private Integer maxPeople;
#Column(name = "is_enabled")
private Boolean isEnabled;
// GETTER AND SETTER METHODS
}
Representing a room of an accomodation, it contains this annoted field:
#ManyToOne
#JoinColumn(name = "id_accomodation_fk", nullable = false)
private Accomodation accomodation;
And finally the Accomodation entity class:
#Entity
#Table(name = "accomodation")
public class Accomodation implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "accomodation")
private List<Room> rooms;
#Column(name = "accomodation_name")
private String name;
#Column(name = "description")
#Type(type="text")
private String description;
// GETTER AND SETTER METHODS
}
Ok, so now I have this Spring Data JPA repository class for RoomTipology:
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface RoomTipologyDAO extends JpaRepository<RoomTipology, Long> {
}
Here I want to define a named query method that return to me the list of all the RoomTipology object related to a specific accomodation, I have done it using SQL and it works fine:
SELECT *
FROM room_tipology as rt
JOIN room r
ON rt.id = r.id_room_tipology_fk
JOIN accomodation a
ON r.id_accomodation_fk = a.id
WHERE a.id = 7
But now I want to translate it in a named query method (or at least using HQL)
How can I do it?
Please Try:
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface RoomTipologyDAO extends JpaRepository<RoomTipology, Long> {
List<RoomTipology> findByRooms_Accomodation(Accomodation accomodation);
}
The query builder mechanism built into Spring Data repository infrastructure is useful for building constraining queries over entities of the repository. The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it
At query creation time you already make sure that the parsed property is a property of the managed domain class. However, you can also define constraints by traversing nested properties.
Doc:Here

Hibernate QueryException: could not resolve property

So I have these relations between these 3 tables
And what I'm trying to do is to search (by code or designation) and get list of projects for a specific chief, something like this:
SELECT * FROM Project p JOIN ProjectHasChief phc ON (p.id = phc.idproject)
JOIN Chief c ON (c.id = phc.id_chief)
WHERE c.id = (myID)
AND (designation LIKE '%user_string%' OR code LIKE '%user_string%');
AND since I'm using hibernate I've used Criteria:
Criteria c = session.createCriteria(ProjectHasChief.class);
c.add(Restrictions.eq("chief", chief))
.add(Restrictions.disjunction()
.add(Restrictions.like("project.designation", reg, MatchMode.ANYWHERE))
.add(Restrictions.like("project.code", reg, MatchMode.ANYWHERE)));
List<ProjectHasChief> list = (List<ProjectHasChief>)c.list();
But I get this error:
org.hibernate.QueryException: could not resolve property: project.designation of: smt.agm.entities.ProjectHasChief
Project entity:
#Entity
#Table(name="projet")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#Column(name="code")
private String code;
#Column(name="designation")
private String designation;
#OneToMany(cascade = CascadeType.ALL, mappedBy="project", orphanRemoval=true)
#OrderBy(clause="id DESC")
private List<ProjectHasChief> chiefs = new ArrayList<ProjectHasChief>();
}
Chief entity:
#Entity
#Table(name="chief")
public class Chief {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#Column(name = "name")
private String name;
}
ProjectHasChief entity:
#Entity
#Table(name="mapping_chantier_chef")
public class ProjectHasChief {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition="serial")
private int id;
#ManyToOne
private Project project;
#ManyToOne
private Chief chief;
#Column(name="date_deb")
private Date startDate;
#Column(name="date_fin")
private Date endDate;
}
Whe hibernate don't know the property designation of Project entity ?!!
Are you absolutely sure all the mappings and joins actually work?
If so, you can try to declare an implicit alias for Project like so:
Criteria c = session.createCriteria(ProjectHasChief.class);
c.createAlias("project", "project") //THIS ONE
c.add(Restrictions.eq("chief", chief))
c.add(Restrictions.disjunction()
.add(Restrictions.like("project.designation", reg, MatchMode.ANYWHERE))
.add(Restrictions.like("project.code", reg, MatchMode.ANYWHERE)));
List<ProjectHasChief> list = (List<ProjectHasChief>)c.list();

Categories