I am creating a simple program in spring boot using JPA to show student and phone number relationship.
CODE
Student Entity
package student.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
#Entity
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
int roll;
#OneToOne
PhoneNumber num;
public Student() {
super();
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getRoll() {
return roll;
}
public PhoneNumber getNum() {
return num;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setRoll(int roll) {
this.roll = roll;
}
public void setNum(PhoneNumber num) {
this.num = num;
}
}
PhoneNumber Entity
package student.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
#Entity
public class PhoneNumber {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
String num;
String type;
#OneToOne
Student stu;
public PhoneNumber() {
super();
}
public PhoneNumber(String num, String type) {
super();
this.num = num;
this.type = type;
}
public Long getId() {
return id;
}
public String getNum() {
return num;
}
public void setId(Long id) {
this.id = id;
}
public void setNum(String num) {
this.num = num;
}
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
}
Student and Phone number repo
package student.repo;
import org.springframework.data.repository.CrudRepository;
import student.entity.Student;
public interface StudentRepo extends CrudRepository<Student, Long> {
}
package student.repo;
import org.springframework.data.repository.CrudRepository;
import student.entity.PhoneNumber;
public interface PhoneNumberRepo extends CrudRepository<PhoneNumber, Long>{
}
SeedFile to enter dummy data
package student;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import student.entity.PhoneNumber;
import student.entity.Student;
import student.repo.PhoneNumberRepo;
import student.repo.StudentRepo;
#Component
public class SeedDb implements CommandLineRunner {
private StudentRepo studentRepo;
private PhoneNumberRepo phoneNumberRepo;
public SeedDb(StudentRepo studentRepo, PhoneNumberRepo phoneNumberRepo) {
super();
this.studentRepo = studentRepo;
this.phoneNumberRepo = phoneNumberRepo;
}
#Override
public void run(String... args) throws Exception {
System.out.println("######################");
Student stu1 = new Student();
stu1.setName("X");
stu1.setRoll(4);
PhoneNumber p = new PhoneNumber("9090909090","Home");
phoneNumberRepo.save(p); //saving phone number to database
stu1.setNum(p);
studentRepo.save(stu1);
}
}
In this program (in seedDb file), I have to manually save the Phone number using phoneNumberRepo before setting it to the student but there are tutorials online where this step is not needed.
Also, the id of student is not saved to the phone number as shown in screenshot
Please tell me how to set PhoneNumber to student without saving it to the database i.e. when I save student, phoneNumber automatically get saved to the database and how to set id of student to the Phone number automatically.
The problem in your code is that you set the PhoneNumber in your Student, but you never set the Student in your PhoneNumber.
As for the bidirectional relationship, you need to use the cascade parameter in the #OneToOne annotation of one of the two entity you're creating the relationship out of. The rule of the thumb is, cascading should be done from parent to children. In your case, the Student is the parent class, so you should do the following:
#OneToOne(cascade = CascadeType.ALL)
PhoneNumber num;
And create a student like so:
Student student = new Student();
student.setName("John Doe");
student.setRoll(4);
PhoneNumber phoneNumber = new PhoneNumber("9090909090", "Home");
student.setNum(phoneNumber);
phoneNumber.setStu(student);
studentRepository.save(student);
Result:
Related
I am trying to return a search bar of results based on a food's name on my front end. Therefore on the backend, I need to have a GetMapping that returns all data based on name. Basically, I want to find all food products by name. Is it possible to do this without using the Serial Key ID?
Here is my model:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="food")
public class Food {
#Id
#Column
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="category")
private String category;
#Column
private String name;
#Column
private String price;
#Column
private String image;
#Column
private String description;
public int getId() {
return id;
}
// public void setId(int id) {
// this.id = id;
// }
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Here is my Repo
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.winecoff.backend.models.Food;
#Repository
public interface FoodRepository extends JpaRepository<Food, Integer> {
List<Food> findByName(String name);
List<Food> findByCategory(String category);
}
Here is my Controller
package com.winecoff.backend.controllers;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.winecoff.backend.exceptions.ResourceNotFoundException;
import com.winecoff.backend.models.Food;
import com.winecoff.backend.repositories.FoodRepository;
#RestController
#CrossOrigin
#RequestMapping("/api/v1/")
public class FoodController {
#Autowired
private FoodRepository foodRepo;
// Read and return all food items
#GetMapping("allfood")
public List<Food> getAllFood(){
return foodRepo.findAll();
}
// This is where I am having trouble
#GetMapping("food/name")
public List<Food> findAllByFoodName(String name) {
return (List<Food>) foodRepo.findByName(name);
}
//Read and return all by category
#GetMapping("food/category/{category}")
public List<Food> findByCategory(#PathVariable String category){
return (List<Food>) foodRepo.findByCategory(category);
}
// Get food item by id
#GetMapping("food/{id}")
public ResponseEntity<Food> getFoodById(#PathVariable int id){
Food food = foodRepo.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Food not found."));
return ResponseEntity.ok(food);
}
// Delete by id
// Question: Wont this change the whole menu and not whats just in the cart?
#DeleteMapping("food/{id}")
public ResponseEntity<String> deleteFood(#PathVariable int id) {
foodRepo.findById(id);
// .orElseThrow(() -> new ResourceNotFoundException("Student not found."));
// Delete method from jpa
foodRepo.deleteById(id);
return new ResponseEntity<>("Food has been deleted", HttpStatus.OK);
}
// add food to api
#PostMapping("addfood")
public Food newFood(#RequestBody Food food) {
return foodRepo.save(food);
}
// update food obj keys, such as name to the api
#PutMapping("food/{id}")
public ResponseEntity<Food> updateFood(#PathVariable int id, #RequestBody Food newFoodInfo){
Food foundFood = foodRepo.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Food not found."));
foundFood.setCategory(newFoodInfo.getCategory());
foundFood.setName(newFoodInfo.getName());
foundFood.setPrice(newFoodInfo.getPrice());
// foundFood.setId(newFoodInfo.getId());
Food updatedFood = foodRepo.save(foundFood);
return ResponseEntity.ok(updatedFood);
}
}
yes you can do custom query in your repo:
try
#Query(value="your query")
List<Food> getFoodByFilter(#Param("filter") String filter);
this page can help you: https://www.baeldung.com/spring-data-jpa-query
You can use #Query annotation and write your own custom query.
#Query("SELECT e FROM food e WHERE e.name = :name")
List<Food> findByName(#Param("name") String name);
or create a custom repository class implements from the FoodRepository interface and create custom queries.
#PersistenceContext
private EntityManager entityManager;
#Override
public List<Food> findAllByFoodName(String name) {
String query = String.format("SELECT * FROM food WHERE name = '%s' ", name);
Query q = entityManager.createNativeQuery(query);
List<Food> result = q.getResultList();
return result;
}
Student has multiple laptops. Student oneToMany Laptop mapping
Student.java
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class Student {
#Id
private int id;
private StudentName studentName;
private String email;
#OneToMany(mappedBy = "student")
private List<Laptop> laptops = new ArrayList<Laptop>();
public Student() {
}
public Student(int id, StudentName studentName, String email) {
this.id = id;
this.studentName = studentName;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public StudentName getStudentName() {
return studentName;
}
public void setStudentName(StudentName studentName) {
this.studentName = studentName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Laptop> getLaptop() {
return laptops;
}
public void setLaptop(List<Laptop> laptops) {
this.laptops = laptops;
}
#Override
public String toString() {
return "Student [id=" + id + ", studentName=" + studentName + ", email=" + email + "]";
}
}
Laptop.java
package com.practice.hibernateDemo.enity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Entity
public class Laptop {
#Id
private int lid;
private String lName;
#ManyToOne
#JoinColumn(name="student_id", referencedColumnName="id")
private Student student;
public Laptop() {
}
public int getLid() {
return lid;
}
public void setLid(int lid) {
this.lid = lid;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
#Override
public String toString() {
return "Laptop [id=" + lid + ", lName=" + lName + "]";
}
}
Main class
package com.practice.hibernateDemo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.practice.hibernateDemo.enity.Laptop;
import com.practice.hibernateDemo.enity.Student;
import com.practice.hibernateDemo.enity.StudentName;
public class CreateStudent {
public static void main(String[] args) {
Laptop laptop = new Laptop();
laptop.setLid(100);
laptop.setlName("HP");
Student student = new Student();
student.setId(101);
student.setEmail("test#gmail.com");
student.setStudentName(new StudentName("test1","test2", "test3"));
student.getLaptop().add(laptop);
Configuration con = new Configuration().configure().addAnnotatedClass(Student.class).addAnnotatedClass(Laptop.class);
SessionFactory sf = con.buildSessionFactory();
Session session = sf.getCurrentSession();
Transaction tx = session.beginTransaction();
session.save(laptop);
session.save(student);
tx.commit();
}
}
After saving the object , foreign key in laptop table is setting as null
lid lName student_id
100 HP NULL
Anyone know where I did wrong mapping due to which I am getting foreign key as null
Thanksin advance
The "many" side of a 1:many relationship is always the owning side. If the relationship is bidirectional, then the other side will carry a mappedBy attribute, just like the non-owning side of a bidirectional 1:1 relationship. It is the relationship field on the owning side that is meaningful for conveying the relationship to the persistence layer, and you have failed to set that.
For example,
laptop.setStudent(student);
I have two bean classes Student and Course which has many to many relationship with each other. For eg. one student can register for multiple courses and vice versa. I have used HibernateTemplate to save objects into Oracle DB. Following are Student, Course and StudentDao classes.
Student Class
package com.springhibernate;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity
#Table(name="Student")
public class Student {
private int studentId;
private String firstName;
private String lastName;
private Set<Course> courses;
#Id
#Column(name="student_id")
public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
#Column(name="first_name")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="last_name")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "Student_Course", joinColumns = #JoinColumn(name = "student_id"), inverseJoinColumns = #JoinColumn(name = "course_id"))
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
StudentDao class
package com.springhibernate;
import java.util.List;
import org.springframework.orm.hibernate3.HibernateTemplate;
public class StudentDao {
private static Helper helper = new Helper();
HibernateTemplate template;
public void setTemplate(HibernateTemplate template) {
this.template = template;
}
// method to save student
public void saveStudent(Student s) {
template.save(s);
}
// method to return one employee of given id
public Student getById(int id) {
Student s = (Student) template.get(Student.class, id);
return s;
}
public List<Course> findCourse(){
List<Course> list = template.find("from Course");
return list;
}
}
Course Class
package com.springhibernate;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity
#Table(name="Course")
public class Course {
private int courseId;
private String courseName;
private Set<Student> students;
#Id
#Column(name="course_id")
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
#Column(name="course_name")
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
#ManyToMany(cascade=CascadeType.ALL,mappedBy="courses")
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
#Override
public int hashCode() {
// TODO Auto-generated method stub
return this.courseId;
}
#Override
public boolean equals(Object o) {
// TODO Auto-generated method stub
Course temp = (Course) o;
return (this.courseId==temp.courseId);
}
}
I have following two queries
I am able to save data in student_course table successfully. I was wondering if I want to retrieve data from student_course table, how can I do it using HibernateTemplate or is there any other way to do so?
For example, query is like
select course_id from student_course where student_id=1
Please note I want just the course id column not complete row.
If in student_course table I want one more column say course_name (from course table), how can I do that?
You can do it in the following way, but keep in mind that the HibernateTemplate is an old API and you should use for example the EntityManager(Factory).
You can get it via the Peristence class.
hibernateTemplate.execute(new HibernateCallback<List>() {
public String doInHibernate(Session s)
throws HibernateException, SQLException {
SQLQuery sql=s.createSQLQuery("select course_id from student_course where student_id=?");
sql.setParameter(0, adventureId);
sql.addScalar(studentID);
return sql.list();
}
});
code for employee.java
package Data;
import java.io.Serializable;
import java.util.*;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
#Entity
public class Employee implements Serializable {
private int empid;
private String empName;
private String empEmailAddress;
private boolean isActive;
private String empAddress;
private String empphone;
#OneToMany
private List<Department> deptobj;= new ArrayList<Department>();
private String emprole;
private Integer salary;
public void setdeptobj(List<Department> deptobj) {
this.deptobj; = deptobj;
}
public List<Department> getdeptobj() {
return deptobj;;
}
public void setempEmailAddress(String empEmailAddress) {
this.empEmailAddress = empEmailAddress;
}
public String getempEmailAddress() {
return empEmailAddress;
}
public boolean getisActive() {
return isActive;
}
public void setisActive(boolean isActive) {
this.isActive = isActive;
}
public String getempAddress() {
return empAddress;
}
public void setempAddress(String empAddress) {
this.empAddress = empAddress;
}
public String getempphone() {
return empphone;
}
public void setempphone(String empphone) {
this.empphone = empphone;
}
public String getemprole() {
return emprole;
}
public void setemprole(String emprole) {
this.emprole = emprole;
}
public int getsalary() {
return salary;
}
public void setsalary(int salary) {
this.salary = salary;
}
#Id
public int getEmpid() {
return empid;
}
public void setEmpid(int empid) {
this.empid = empid;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
code for Department.java
package Data;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
#Entity
public class Department {
private String dept;
#ManyToOne
private Employee employee;
#Id
private int deptid;
public String getdept() {
return dept;
}
public void setdept(String dept) {
this.dept = dept;
}
public int getdeptid() {
return deptid;
}
public void setdeptid(int deptid) {
this.deptid = deptid;
}
private Employee getemployee(){
return employee;
}
private void setemployee(Employee employee){
this.employee = employee;
}
}
code for middle layer
package service;
import Data.*;
import static com.mchange.v2.log.MLog.config;
import java.io.Serializable;
import java.util.List;
import javax.imageio.spi.ServiceRegistry;
import javax.persistence.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
public class ServiceLayer {
SessionFactory sessionFactory = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
Session session = sessionFactory.openSession() ;
public void add(Employee emp){
session.beginTransaction();
System.out.println("hello");
session.save(emp);
System.out.println("hello");
session.getTransaction().commit();
}
public void delete(int empid){
session.beginTransaction();
Employee emp = (Employee) session.get(Employee.class, empid);
session.delete(emp);
session.getTransaction().commit();
}
public void update(Employee emp){
session.beginTransaction();
session.update(emp);
session.getTransaction().commit();
}
public void read(){
session.beginTransaction();
String hql = "select * from Employee;";
session.createSQLQuery(hql);
session.getTransaction().commit();
}
public Department check(String dept){
session.beginTransaction();
SQLQuery q = session.createSQLQuery("from Department d where d.dept=:deptname");
q.setParameter("deptname", dept);
Department d = (Department) q.uniqueResult();
session.getTransaction().commit();
return d;
}
public Department getDept(Department list){
session.beginTransaction();
Department deptobj= (Department) session.get(Department.class, (Serializable) list.getdeptid());
session.getTransaction().commit();
return deptobj;
}
public void addDept(Department dep){
session.beginTransaction();
session.save(dep);
session.getTransaction().commit();
}
}
code for mainservice layer
package mainService;
import Data.*;
import static java.sql.Types.NULL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import service.ServiceLayer;
public class Logic {
private int empid;
private String empName;
ServiceLayer sl = new ServiceLayer();
private String empPassword;
private String empEmailAddress;
private boolean isPermanent;
private Calendar empJoinDate;
public void add(String empName,String empEmailAddress,String empAddress,String empphone,String dept,String emprole,Integer salary,boolean active){
Employee emp = new Employee();
emp.setEmpName(empName);
emp.setempAddress(empAddress);
emp.setempEmailAddress(empEmailAddress);
emp.setempphone(empphone);
emp.setemprole(emprole);
emp.setsalary(salary);
emp.setisActive(active);
Department dep = null;
Department list = sl.check(dept);
if(list.getdeptid()==NULL){
dep = addDept(dept);
}
else{
dep = sl.getDept(list);
}
emp.getdeptobj().add((Department) dep);
sl.add(emp);
}
private Department addDept(String dept) {
Department dep = new Department();
dep.setdept(dept);
sl.addDept(dep);
Department list = sl.check(dept);
dep = (Department) sl.getDept(list);
return dep;
}
}
Service layer gets the values from form created in swing then it passes the data to ServiceLayer.java file which creates session and sets the value to create a record and then save that record THE problem is I want to check if department already exists, then link with that for that search will be based on department name given by user if department does not exixt then first create new department and then link with employee.
I am not able to get where the problem is because I haven't used hibernate before... so please help me. And on running the file I am getting the ERROR of
Exception in thread "AWT-EventQueue-0" org.hibernate.MappingException:
Could not determine type for: java.util.List, for columns:
[org.hibernate.mapping.Column(deptobj)])
Either you put JPA annotations on getters, consistently, or you put them on fields, consistently. Mixing both in a single class makes Hibernate ignore all the ones that aren't placed on the same location as the #Id annotation.
Also, your mapping is weird: a department has a single employee, which also belongs to other departments? Is this a mapping for a single-person company doing everything? You probably want the association in the other direction: a department has many employees, and each employee belongs to one department.
I'm trying to persist a List, however I'm getting this error
org.hibernate.MappingException: Could not determine type for: java.util.List, at table: Person, for columns: [org.hibernate.mapping.Column(comments)]
I've used the #ElementCollection annotation as specified in the hibernate documentation. I can't see what else to try.
Please ignore this paragraph is was only required so that i could submit the question.
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.stereotype.Component;
#Component
#Entity
public class Person {
private String name;
private Long id;
private String reviewName;
private String review;
private List<String> comments = new ArrayList<String>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Id
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy="increment")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(columnDefinition="LONGTEXT")
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
public String getReviewName() {
return reviewName;
}
public void setReviewName(String reviewName) {
this.reviewName = reviewName;
}
public List<String> getComments() {
return comments;
}
#ElementCollection
public void setComments(List<String> comments) {
this.comments = comments;
}
public void addComment(String comment) {
getComments().add(comment);
}
}
#elementcollection annotation should be put at getter (getComments()) instead of setter
The problem is that you should have
#ElementCollection(targetClass=String.class)
before every single mention of a collection type (map/list/etc) including both attribute declarations and method declarations.
not before one mention "instead of" another, but everywhere.