JPA - select with join - how to make two related tables - select

I have two tables with relacionship by id_employee.
--------------------------- ---------------------------
table employee table timesheet
--------------------------- ---------------------------
id_employee id_time
name_employee date_entry
--------------------------- quant_hour
id_employee
---------------------------
I need to do a select that returns all records from the table employe and hours in existing related table timesheet. Some employees do not have hours recorded in the timesheet table but should appear in the list because they are registered in the employee table.
What the JPQL query for this ?
Class Employee
#Entity
public class Employee {
#Id #GeneratedValue
private Long id_employee;
private String name_employee ;
//GETS and SETS
}
Class TimeSheet
#Entity
public class Timesheet {
#Id #GeneratedValue
private Long id_time;
private Double quant_hour;
private Date date_entry;
#ManyToOne
private Employee employee;
//GETS and SETS
}

Provided that both tables are mapped correctly,the Employee entity will have an attribute (or collection) of type Timesheet entity, therefore, you only need to get the list of employees:
SELECT e FROM Employee e
JPA automatically retrieves the Timesheet (or list of Timesheets) when you want to read it from the Employee entity.

Related

JPA join same child table with a differen key

I have situation that the same table is linked two different keys
all names either it manager's name or name of the employee stored in "employee_table" reason is manager is also an employee
manager_link_table
id
manager_id
employee_table
id
name
Now I want two child objects as below
I am trying to create JPA Entity with OneToOne as
#Entity
#Table(name="manager_link_table")
class ManagerLinkTable {
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn( name="id", referencedColumnName="id")
private EmployeeTable employee;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn( name="id", referencedColumnName="manager_id")
private EmployeeTable manager;
}
#Entity
#Table(name="employee_table")
class EmployeeTable {
private String id;
private String name;
}
I am writing JPA query as
SELECT m FROM ManagerLinkTable m
I want m.employee.name and m.manager.name to be different
But I am getting the same, it seems the referencedColumnName is ignored while joining the table
Does anyone faced this issue ?

Save entity with Spring data, persistence & db contraints

In my project I have e.g. an Employee which has several Mobile which has additional attributes, e.g.
Jon Doe, +911, private
Jon Doe, 123456, company
Jon Doe, 8978, company,
Mara Smith, 7888, private
Mara Smith, 458, company
and therefore I create
#Entity
public class Employee {
#Id
private int id;
#OneToMany(mappedBy="emp")
private List<Mobile> lstMobiles;
...
}
and for the Mobile I have
#Entity
#IdClass(MobileKey.class)
public class Mobile {
#Id
private String phoneNo;
#Id
#JoinColumn(name = "emp_id")
private Employee emp;
...
}
class MobileKey{
private String phoneNo;
private int emp;
....
}
The database has tables Employee, Mobile. The table Mobile first two columns are
emp_id (as int)
phoneNo (as String)
up till now nothing special except that the database has a foreign constraint, namely that the emp_id has to exist in the table Employee. Otherwise the phoneNo does not make much sense.
The major problem I'm facing right now is that I need to store Jon Doe or Mara Smith. If I use e.g.
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
}
with some Autowired variable as e.g. employeeRepo.save(newEmployee) than I get from the database a constraint violation. This is due to the fact that the Mobile is attempted to be inserted before the Employee is created in the table :-(
I guess that the design of Employee and the Mobile is somehow wrong - especially with the list and the relation. But could be as well be related with the Spring-Data configuration.

Model Look up table for a JPA Entity Field

I'm trying to find out the appropriate relationship to be used in order to model an JPA Entity Field which needs a Look-up table (Comboxbox equivalent on the UI) to select the value from. An example below:
#Entity
public class Employee {
#Id
private int employeeId;
private String name;
private Department department;
}
#Entity
public class Department {
#Id
private int id;
private String name;
}
The instances of Department could be as follows:
Id | Name
-----------------------
100 | Human Resources
101 | Sales
102 | Finances
For an employee, the department field should get a value from one of the above. What should be the JPA annotations for the corresponding fields in both the entities?
Thanks,
Sandeep Joseph
I think you are looking for a unidirectional ManyToOne relationship from Employee to Department, something like this:
#Entity
public class Employee {
#Id
private int employeeId;
private String name;
#ManyToOne
#JoinColumn(name = "department_id", nullable = false)
private Department department;
}
This means an employee must be associated to a single department and a department can be associated to many employees.
If you need to know the list of employees associated to a department then you can make the relationship bidirectional by adding this:
#Entity
public class Department {
#Id
private int id;
private String name;
#OneToMany(mappedBy = "department")
private Collection<Employee> employees;
}

ManyToOne doing multiple queries to fetch records

I have two entities, and dept_id is the foreign key here.
public class Student implements Serializable {
...
#Id
#Column(name="id")
private Integer id;
#ManyToOne
#JoinColumn(name = "dept_id")
private Department department;
...
}
and
public class Department implements Serializable {
...
#Id
#Column(name="id")
private Integer id;
#Column(name = "name")
private String name;
...
}
Now I am doing the following JPQL where I have around 100 parameters inside in query:
select o from Student o where o.id in(1,2,7,9,15,16, ...)
When I see the JPA log, I found it is fetching 100 records from the Student by one query. After that it is doing 100 separate queries to fetch the Department for each Student. So far my understanding is the I/O operation should be slow. Is there any way so that it fetches everything by a single query?
I found this worked for me:
query.setHint("eclipselink.join-fetch", "o.department");
Also, I found this one is handy as it does not make any joining, but fetches the records separately in a bulk.
query.setHint("eclipselink.batch", "o.department");

JPA annotation to add and view values from a reference table

Say I have this class:
#Entity
#Table(name="PICTURE")
public class Picture{
private String category1, category2;
}
but the database structure looks like this:
TABLE PICTURE {
int category1;
int category2;
...
}
TABLE PICTURE_REF {
int category;
String categoryName;
...
}
How would I use JPA annotations on Picture so that any time I request an instance of it, category1 and category2 contains the categoryName from the PICTURE_REF table instead of the actual integer id stored in the PICTURE table?
I'm also wondering how saves would work because the user would select a category from a dropdown and the corresponding category integer ID would be what's stored in the PICTURE table.
From your description , PICTURE.category1 and PICTURE.category2 have the many-to-one relationship to the PICTURE_REF
The following shows the bi-directional mapping between them using annotation:
For table PICTURE:
#Entity
#Table(name="PICTURE")
public Class Picture{
#Id
private Integer id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "category1")
private PictureRef category1,
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "category2")
private PictureRef category2;
//getter and setters
}
For table PICTURE_REF:
#Entity
#Table(name="PICTURE_REF")
public Class PictureRef{
#Id
private Integer id;
#OneToMany(mappedBy = "category1")
List <Picture> listOfCat1Picture= new ArrayList<Picture>();
#OneToMany(mappedBy = "category2")
List <Picture> listOfCat2Picture= new ArrayList<Picture>();
//getter and setters
}
Important Points:
#Entity marks the java class as an hibernate entity. It is mapped to the name of the table specified in the #Table
Use #ManyToOne to define the many-to-one relationship
In the relational database , many-to-one relationship is expressed by using the following foreign key constraint:
"Many side table" has a FK column which only accepts the PK of the "one side table".
In your case , these FK columns are PICTURE.category1 and PICTURE.category2. The name of these FK columns can be explicitly defined by the name attribute of #JoinColumn.
FetchType.EAGER makes that PictureRef will be eagerly fetched whenever Picture is loaded or get
Depending on your requirement , you can do the unidirectional mapping by omitting #OneToMany in the PictureRef.It will also work .But given PictureRef , you cannot access its Picture
Given a Picture instance , you can get its categoryName and categoryId by
picture.getCategory1().getCategoryName()
picture.getCategory1().getId()
picture.getCategory2().getCategoryName()
picture.getCategory2().getId()
If you can't modify the schema
You can modify your mapping so Category is an entity instead of just a String. Then you would have a OneToOne or (more likely) a ManyToOne from Picture to Category for category1 and category2.
If you CAN modify the schema
You can use an ElementCollection on Picture to store a List instead of having category1 and category2. This would give you a schema something like
TABLE PICTURE {
long key;
}
TABLE PICTURE_CATEGORY {
long picture_key;
String category_name;
}
OR you can again map Category to an entity and use a ManyToMany from Picture to Category which would give you a schema like
TABLE PICTURE {
long key;
...
}
TABLE PICTURE_CATEGORY {
long picture_key;
long category_key;
}
TABLE CATEGORY {
long key;
String name;
}
As for saving, you will can use a converter in whatever your view technology is that will converter from key to Category, or you can load the Category from the key in your controller and set it in the Picture before you save. I doubt you'll want saving a Picture to cascade into a Category.