How to use relationships between tables in jpa - java

I am learning jpa on my own by using online tutorials & trying out possible examples but now i am little confused about how to use relationships between tables. I have 3 classes having #Entity annotation which means jpa will create table based on these classes.i have id field in Student, Course, Booking classes and they will be primary key for respective tables.
The help i need is, in Booking class there is sid & cid fields and i want them to be referenced such as sid(Student.java)=sid(Booking.java) & cid(Course.java)=cid(Booking.java) and the scenario is each student can one or multiple bookings of one or multiple course. can someone tell me how & where should i use #OnetoOne, #OnetoMany, #ManytoMany, #ManytoOne in my code.
Student.java
package com.testapp;
import java.util.List;
import javax.persistence.*;
#Entity
public class Student{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int sid;
private String name;
private int salary;
//Getters and Setters....
..
public Student() {
super();
}
public Student(int sid, String name, float salary) {
super();
this.sid = sid;
this.name = name;
this.salary = salary;
}
public Student(String name, float salary) {
super();
this.name = name;
this.salary = salary;
}
}
Course.java
package com.testapp;
import java.util.List;
import javax.persistence.*;
#Entity
public class Course {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int cid;
private String cname;
private int price;
//Getters and Setters....
..
public Course() {
super();
}
public Course(int cid, String cname, int price) {
super();
this.cid = cid;
this.cname = cname;
this.price = price;
}
public Course(String cname, int price) {
super();
this.cname = cname;
this.price = price;
}
}
Booking.java
package com.testapp;
import java.util.Set;
import javax.persistence.*;
#Entity
public class Booking {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int bid;
private String date;
private int sid;
private int cid;
//Getters and Setters....
..
public Booking() {
super();
}
public Booking(int bid, String date, int sid, int cid) {
super();
this.bid = bid;
this.date= date;
this.sid = sid;
this.cid = cid;
}
public Booking(String date, int sid, int cid) {
super();
this.date = date;
this.sid = sid;
this.cid = cid;
}
}
Thank You..

Just define object in you class, as an example student involving many Cource , then you can define property on student class like below
public class Student{
private List<Cource> cources;
}
then orm detects the relationship, but also you have annotations like #OneToMant #ManyToMany in JPA

The best way to define this relationship in your case will be Student and Course will have OneToMany relation with Booking. And Booking will have ManyToOne relation with Student and Course
Student.java
#OneToMany(mappedBy = "student", cascade = CascadeType.ALL, orphanRemoval = true)
public Set< Booking > getBookings() {
return bookings;
}
Course.java
#OneToMany(mappedBy = "course", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<Booking> getBookings() {
return bookings;
}
Booking.java
#Entity
public class Booking {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int bid;
private String date;
private Student student;
private Course course;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "sid")
public Student getStudent() {
return student;
}
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cid")
public Course getCourse() {
return course;
}
//Getters and Setters....
..
public Booking() {
super();
}
}

You should not use primary keys of other entities in JPA!
Use #ManyToOne and Student as well as Cource instead of sid and cid.

Related

Employee Tracker . setting table relationship using mysql and java spring boot

I am using Java and Sprig boot with MySQL to create an employee tracker. there are to models: Employee and Company. The Company model just has an autogenerated Id and name. The employee has first_name, last_name, address, salary, company_id, and email_id. The Employee Model belongs to Company model, and it is a oneToMany relationship (because one company has many employees. I am trying to set it up so that the Employee model is linked to the Company model. When I try and run spring boot i get this error:
Use of #OneToMany or #ManyToMany targeting an unmapped class: employeeapps.com.example.EmployeeTracker.model.Employee.company[employeeapps.com.example.EmployeeTracker.model.Company]
Here is my Employee Model:
package employeeapps.com.example.EmployeeTracker.model;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "employees")
public class Employee {
//Company is one and has many employees
#OneToMany(mappedBy = "employees")
private Set<Company> company;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long companyId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name="address")
private String address;
#Column(name="salary")
private Double salary;
#Column(name = "email_id")
private String emailId;
//default constructor
public Employee(){
}
//create a public constructor with the appropriate parameters to be able to create a new instance of an employee
public Employee(String firstName, String lastName, String emailId, String address, Double salary){
super();
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
this.salary = salary;
this.address = address;
}
//define methods
//long data type because could be a very long numerical data
public long getId() {
return companyId;
}
public void setId(long companyId){
this.companyId = companyId;
}
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getLastName(){
return lastName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getEmailId(){
return emailId;
}
public void setEmailId(String emailId){
this.emailId = emailId;
}
public void setAddress(String address){
this.address = address;
}
public void setSalary(Double salary){
this.salary = salary;
}
Here is my Compay Model:
package employeeapps.com.example.EmployeeTracker.model;
import javax.persistence.*;
#Table(name = "company")
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "name")
private String name;
public Company(){
}
//public constructor
public Company(String name){
this.name = name;
}
}
Here is my employee controller to preform REST API:
package employeeapps.com.example.EmployeeTracker.controller;
import employeeapps.com.example.EmployeeTracker.model.Employee;
import employeeapps.com.example.EmployeeTracker.repository.employeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/api/v1")
public class EmployeeController {
#Autowired
private employeeRepository employeeRepository;
//REST APIS
//get all employees method name is get all
#GetMapping("/employees")
public List<Employee> getAllEmployees(){
return employeeRepository.findAll();
}
}
In the company model give the model #Entity annotation above #Table annotation.
Add below line to your system.properties file
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
In employees class use :
#OneToMany(targetEntity = Employee.class,cascade = ALL,fetch =
FetchType.LAZY)
#JoinColumn(name = "employee_id",referencedColumnName = "company_id")
private Set<Company> company;
You should make the company an entity because you cannot make mapping without making the model class into the entity.Use #Entity to make company class entity above #Table(name = company).
As you are trying to map from employees(many) entity to company(one)entity
try #ManyToOne mapping in the employees entity by making company_
id a FOREIGN KEY in employee table
#ManyToOne
#JoinColumn(name="id",referencedColumnName="company_id")
private Set<Company> company;
In the above name represents id of company in company entity and referencedColumnName represents company_id in the employee entity.

Spring Boot REST Hibernate - Get all the cities of a state

I have a database with following tables -
My State Table
with columns - id and state
My City Table
with columns - id, city and state_id
And I want to get all the cities when i request get request with a particular state id to get its cities.
State Entity Class -
#Entity
#Table(name = "states")
public class State {
#Id
private int id;
private String state;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "state_id")
private List<City> cities = new ArrayList<>();
public State() {
}
public long getId() {
return id;
}
public String getState() {
return state;
}
}
City Entity Class -
#Entity
#Table(name = "cities")
public class City {
#Id
private long id;
private String city;
private int state_id;
public City() {
}
public long getId() {
return id;
}
public String getCity() {
return city;
}
public int getState_id() {
return state_id;
}
}
How can I get this to work ?
any help is appreciated.

Joining two entities in spring-boot

I have a category table that have its own unique id and name,
I have a product table that have its own unique id, name, price and categoryId.
Category.java
#Entity
public class Category {
#Id
#GeneratedValue
private long id;
private String name;
#OneToMany(fetch=FetchType.LAZY, mappedBy = "category")
private Set<Product> products;
//getters and setters
}
Product.java
#Entity
public class Product {
#Id
private long productId;
private String name;
private double price;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="categoryId")
private Category category;
public Product() {
}
public Product(long productId, String name, double price) {
super();
this.productId = productId;
this.name = name;
this.price = price;
}
public long getProductId() {
return productId;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
When I try to create a new product by post method, I should be able to read or write it's categoryId, but I can't. What am I doing it wrong?
You should not be able to write its categoryId, but you need a getter and a setter for Product.category. To change the category of a product, you would do product.setCategory(newCategory). If you want to READ the category ID of a product, you also need to add a getter for Category.id; you would then do: product.getCategory().getId().

MappingException: Repeated column in mapping for entity: ... column: dept_id (should be mapped with insert="false" update="false")

I know there are similar questions here, but for some reason they just don't work for me. Here, I can't even find which column is repeated. The basic idea of the system is that using a join on deptId (FK), I can get all the employees in a certain department.
I have reproduced below the relevant code:
Employee.java
package com.tvlk.advDemo.model;
import javax.persistence.*;
import javax.swing.*;
import java.io.Serializable;
#Entity
#Table(name="employees")
public class Employee implements Serializable {
private long id;
private String name;
private String designation;
private long deptId;
private Department department;
public Employee() {
}
public Employee(String name, String designation, long deptId) {
this.name = name;
this.designation = designation;
this.deptId = deptId;
}
#Id
#GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "designation", nullable = false)
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
// #Column(name = "deptId", nullable = false)
public long getDeptId() {
return deptId;
}
public void setDeptId(long deptId) {
this.deptId = deptId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "deptId", nullable = false)
public Department getDepartment() {
return department;
}
public void setDepartment(Department department){
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", designation=" + designation + ", deptId=" + deptId
+ "]";
}
}
Here is Department.java
package com.tvlk.advDemo.model;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity
#Table(name="departments")
public class Department implements Serializable {
private long id;
private String deptName;
private String deptHead;
private long budget;
private List<Employee> employees;
public Department(){
}
public Department(long id, String deptName, String deptHead, long budget)
{
this.id = id;
this.deptHead = deptHead;
this.deptName = deptName;
this.budget = budget;
}
#Id
public long getId() {return id;}
public void setId(long id) {this.id = id; }
#Column(name = "name", nullable = false)
public String getDeptName(){return deptName;}
public void setDeptName(String deptName){this.deptName = deptName; }
#Column(name = "deptHead", nullable = false)
public String getDeptHead(){return deptHead; }
public void setDeptHead(String deptHead){this.deptHead = deptHead; }
#Column(name = "budget", nullable = false)
public long getBudget(){return budget;}
public void setBudget(long budget){this.budget = budget; }
#OneToMany(fetch = FetchType.LAZY, mappedBy = "id", targetEntity = Employee.class)
public List<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
Any help will be appreciated, I am quite new to springboot and hibernate. Note that I am making REST APIs for CRUD operations using H2.
I think you have multiple fields that contains same name. That's the reason for repeated column.
Example:
private long deptId;
`#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "deptId", nullable = false)
public Department getDepartment() {
return department;
}`
There is already a column named depId (long type in ur field) and again you are trying to add Department with same column name ( #JoinColumn(name = "deptId", nullable = false) ) in your Joincolumn name. Try to change the JoinColumn name or add different column name to long datatype field.

I cannot get One-to-one relationship and inheritance to work simultaneously in Hibernate

I am new to Hibernate and learning all the different annotations can be frustrating at times. Currently, I am stuck on making Doctor extend Person and also have a 1-to-1 relationship between Doctor and Specialty. I've been stuck on this for a while and still cannot figure this one out. I've tried testing out one of the two relationships and my code works fine, but I encounter a problem when I put everything together.
this is the error I'm getting:
Exception in thread "main" org.hibernate.MappingException: Could not
determine type for: edu.cs157b.medicalSystem.Specialty, at table:
Person, for columns: [org.hibernate.mapping.Column(specialty)]
Doctor:
package edu.cs157b.medicalSystem;
import javax.persistence.*;
#Entity
public class Doctor extends Person {
#OneToOne
#JoinColumn(name = "SPECIALTY_ID")
private Specialty specialty;
private double salary;
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSpecialty(Specialty specialty) {
this.specialty = specialty;
}
public Specialty getspecialty() {
return specialty;
}
}
Speciality:
package edu.cs157b.medicalSystem;
import javax.persistence.*;
#Entity
public class Specialty {
#OneToOne
private Doctor doctor;
#Id
#GeneratedValue
#Column(name = "SPECIALTY_ID")
private int sId;
private String specialtyTitle;
public void setSId(int sId) {
this.sId = sId;
}
public int getSId() {
return sId;
}
public void setSpecialtyTitle(String specialtyTitle) {
this.specialtyTitle = specialtyTitle;
}
public String getSpecialtyTitle() {
return specialtyTitle;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
public Doctor getDoctor() {
return doctor;
}
}
Person:
package edu.cs157b.medicalSystem;
import javax.persistence.*;
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Person {
private int personId;
private String first_name;
public Person() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "PERSON_ID")
public int getPersonId() {
return personId;
}
public void setPersonId(int personId){
this.personId = personId;
}
public void setFirstName(String first_name) {
this.first_name = first_name;
}
public String getFirstName() {
return first_name;
}
}
There are two errors in your code.
First, you annotated the getter in Person, and annotated the field in its subclass Doctor. That's why you get this error: once Hibernate sees the #Id annotation on a getter in the base class, it only considers annotations on getters in the rest of the class hierarchy, and ignores the annotations on fields.
Second, your OneToOne bidirectional association is mapped incorrectly. One side must always be the inverse side in a bidirectional association. So, the following field:
#OneToOne
private Doctor doctor;
should be
#OneToOne(mappedBy = "specialty")
private Doctor doctor;
to inform JPA that the Specialty.doctor association is the inverse side of the OneToOne association already declared and mapped in Doctor.specialty.

Categories