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();
}
});
Related
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);
The contact class as an entity that would be linked with address class
package asmt1.demo.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import asmt1.demo.dto.UserStatus;
//#Entity annotation specifies that the class is an entity and is mapped to a database table.
//#Table annotation specifies the name of the database table to be used for mapping
#Entity
#Table(name="Contactdetail")
public class Contact {
//#Id is used to specify the primary key
#Id
//Generated value is used to generate pk value ie. id to be autogenerated and assign identity column(id)
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
//#column is used to specify the column condition
//#Column( unique = true)
private String firstName;
private String lastName;
//#Column(unique = true)
private long contactNo;
private String mailId;
//list of named constant ie. status
#Enumerated(EnumType.STRING)
private UserStatus status;
//it is used to create one-to-one relationship between the contact and address table
//fetch type.lazy tells Hibernate to only fetch the related entities from the database when you use the relationship
#ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
#JoinTable(name="conadd",
joinColumns = {#JoinColumn(name="id")},
inverseJoinColumns = {#JoinColumn(name="addid")})
//To handle the problem related to the serialization of the model using Jackson API when the model attributes have a lazy loading defined,
//we have to tell the serializer to ignore the chain or helpful garbage that Hibernate adds to classes, so it can manage lazy loading of data by declaring #JsonIgnoreProperties
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Set<Address> address=new HashSet<>();
//generate getters,setters, toString() and constructor using fields
public Contact() {}
public Contact(String firstName, String lastName, long contactNo, String mailId, UserStatus status,
Set<Address> address) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.contactNo = contactNo;
this.mailId = mailId;
this.status = status;
this.address = address;
}
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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 long getContactNo() {
return contactNo;
}
public void setContactNo(long contactNo) {
this.contactNo = contactNo;
}
public String getMailId() {
return mailId;
}
public void setMailId(String mailId) {
this.mailId = mailId;
}
public UserStatus getStatus() {
return status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
#Override
public String toString() {
return "Contact [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", contactNo=" + contactNo
+ ", mailId=" + mailId + "]";
}
}
the address class which is the entity
package asmt1.demo.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
//#Entity annotation specifies that the class is an entity and is mapped to a database table.
//#Table annotation specifies the name of the database table to be used for mapping
#Entity
#Table(name="addressDetail")
public class Address {
//#Id is used to specify the primarykey
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long addid;
private String street1;
private String street2;
private long zipcode;
private String city;
private String state;
private String Country;
//mappedby is used to specify to relationship
#ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,mappedBy = "address")
private Set<Contact> contact=new HashSet<>();
//generate getters,setters, toString() and constructor using fields
public long getId() {
return addid;
}
public Set<Contact> getContact() {
return contact;
}
public void setContact(Set<Contact> contact) {
this.contact = contact;
}
public void setId(long id) {
this.addid = id;
}
public String getStreet1() {
return street1;
}
public void setStreet1(String street1) {
this.street1 = street1;
}
public String getStreet2() {
return street2;
}
public void setStreet2(String street2) {
this.street2 = street2;
}
public long getZipcode() {
return zipcode;
}
public void setZipcode(long zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
public Address(String street1, String street2, long zipcode, String city, String state, String country) {
super();
this.street1 = street1;
this.street2 = street2;
this.zipcode = zipcode;
this.city = city;
this.state = state;
Country = country;
}
public Address() {}
}
a request class where I was calling both for data uploading
package asmt1.demo.dto;
import java.util.HashSet;
import java.util.Set;
import asmt1.demo.entity.Address;
import asmt1.demo.entity.Contact;
public class AddressReq {
private Set<Address> address=new HashSet<>();
private Set<Contact> contact=new HashSet<>();
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
public Set<Contact> getContact() {
return contact;
}
public void setContact(Set<Contact> contact) {
this.contact = contact;
}
public AddressReq(Set<Address> address, Set<Contact> contact) {
super();
this.address = address;
this.contact = contact;
}
public AddressReq() {}
#Override
public String toString() {
return "AddressReq [address=" + address + ", contact=" + contact + "]";
}
}
enum class for status
package asmt1.demo.dto;
//constant value for userstatus class
public enum UserStatus {
ACTIVE,INACTIVE
}
controller class
package asmt1.demo.controller;
import java.util.List;
import java.util.NoSuchElementException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RestController;
import asmt1.demo.converter.ContactConverter;
import asmt1.demo.dto.AddressReq;
import asmt1.demo.dto.ContactDto;
import asmt1.demo.entity.Contact;
import asmt1.demo.repository.AddressRepo;
import asmt1.demo.repository.ContactRepo;
//#restcontroller is used for restful services
#RestController
//#RequestMapping is used for creating baseurl for controller will be used
#RequestMapping("/contact")
public class ContactController {
//#Autowired will search the object of class
#Autowired
private ContactRepo ctrepo;
#Autowired
private AddressRepo addrepo;;
#Autowired
private ContactConverter converter;
//#Requestbody is used to map/bind methods with pojo pr value to return value to the web
//#postmapping is used to add data to database from web
#PostMapping("/add")
public List<Contact> newcontact(#RequestBody AddressReq req) {
return ctrepo.saveAll(req.getContact());
}
//#getmapping is used to get the details/records from database on web page
#GetMapping("/contactlist")
public List<Contact> getcontactlist(){
return ctrepo.findAll(Sort.by(Sort.Direction.ASC, "firstName","lastName"));
}
#GetMapping("/contactdto")
public List<ContactDto> getcontactlistdto(){
List<Contact> findAll=ctrepo.findAll();
return converter.entitytodto(findAll);
}
#GetMapping("/contactlist/{id}")
public ResponseEntity<Contact> get(#PathVariable Long id) {
try {
Contact contact = ctrepo.getOne(id);
return new ResponseEntity<Contact>(contact, HttpStatus.OK);
} catch (NoSuchElementException e) {
return new ResponseEntity<Contact>(HttpStatus.NOT_FOUND);
}
}
#GetMapping("/contactdto/{id}")
public ContactDto getbyid(#PathVariable Long id) {
Contact orElse=ctrepo.findById(id).orElse(null);
return converter.entitytodto(orElse);
}
#GetMapping("/orderlist")
public List<Contact> getcontactlistbyorder(){
return ctrepo.findAllByOrderByIdDesc();
}
#PostMapping("/save")
public ContactDto savedto(#RequestBody ContactDto dto) {
Contact contact=converter.dtotoentity(dto);
contact=ctrepo.save(contact);
return converter.entitytodto(contact);
}
//#deletemapping is used to delete the records/details from database by web page
#DeleteMapping("/delete/{id}")
public String deletebyid(#PathVariable long id){
if (ctrepo.findById(id)==null) {
return "Id not found.....Please enter correct id";
}
ctrepo.deleteById(id);
return "Successfully deleted "+id;
}
//#putmapping is used to change/update the records/details in database by web page
#PutMapping("/edit")
public List<Contact> editcontactbyid(#RequestBody AddressReq req ){
return ctrepo.saveAll(req.getContact());
}
}
here is the Json format which I was uploading the data but its showing me error that
at [Source: (PushbackInputStream); line: 1, column: 2]]
2021-05-04 12:57:07.799 WARN 876 --- [nio-9090-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.util.HashSet<asmt1.demo.entity.Contact> out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.HashSet<asmt1.demo.entity.Contact> out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 13] (through reference chain: asmt1.demo.dto.AddressReq["contact"])]
{"contact":{
"firstName":"tomu",
"lastName":"shawn",
"contactNo":9124245,
"mailId":"ggia#gmail.com",
"status":"INACTIVE",
"address":{
"street1":"A/wing-24",
"street2":"plotno-4",
"city":"Mumbai",
"state":"Maharashtra",
"country":"India",
"zipcode":705
}}}
In your AddressReq class contact is set that is collection but in your pay load you are sending an object which should be collection of object.
Based on the AddressReq class the pay load should be
{["contact":{
"firstName":"tomu",
"lastName":"shawn",
"contactNo":9124245,
"mailId":"ggia#gmail.com",
"status":"INACTIVE",
"address":{
"street1":"A/wing-24",
"street2":"plotno-4",
"city":"Mumbai",
"state":"Maharashtra",
"country":"India",
"zipcode":705
}
}]
}
or if your request is always single entry of contact then you can change the contact property to single instance not the collection of Contact instance.
I have two Entities CompanyDetail and DriverDetail
CompanyDetail
package com.javarnd.pns.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
#Entity
#Table(name="company_detail")
public class CompanyDetails {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="company_id")
private long companyId;
#Column(name="company_name")
private String companyName;
#Column(name="pan_no")
private String panNo;
private String website;
private String email;
#Column(name="conntact_no")
private String contactNo;
#OneToMany(cascade = CascadeType.ALL)
#LazyCollection(LazyCollectionOption.FALSE)
#JoinTable(name = "COMPANY_VEHICLE_DETAIL", joinColumns = #JoinColumn(name = "company_id"), inverseJoinColumns = #JoinColumn(name = "vehicle_id"))
private List<Vehicle> vehicleList;
#OneToMany(cascade = CascadeType.ALL)
#LazyCollection(LazyCollectionOption.FALSE)
#JoinTable(name = "COMPANY_DRIVER_DETAIL", joinColumns = #JoinColumn(name = "company_id"), inverseJoinColumns = #JoinColumn(name = "driver_id"))
private List<DriverDetail> driverList;
#Column(name="type")
private String companyType;
public long getCompanyId() {
return companyId;
}
public void setCompanyId(long companyId) {
this.companyId = companyId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getPanNo() {
return panNo;
}
public void setPanNo(String panNo) {
this.panNo = panNo;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContactNo() {
return contactNo;
}
public void setContactNo(String contactNo) {
this.contactNo = contactNo;
}
public String getCompanyType() {
return companyType;
}
public void setCompanyType(String companyType) {
this.companyType = companyType;
}
public List<Vehicle> getVehicleList() {
return vehicleList;
}
public void setVehicleList(List<Vehicle> vehicleList) {
this.vehicleList = vehicleList;
}
public List<DriverDetail> getDriverList() {
return driverList;
}
public void setDriverList(List<DriverDetail> driverList) {
this.driverList = driverList;
}
}
DriverDetail
package com.javarnd.pns.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
#Entity
public class DriverDetail {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="driver_id")
private long id;
private String name;
#Column(name="contact_no")
private String contactNo;
#Column(name="license_no")
private String licenseNo;
#ManyToMany(mappedBy="availableDriverList",cascade=CascadeType.ALL)
private List<Vehicle> asignedVehicle;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="company_id")
private CompanyDetails companyDetail;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContactNo() {
return contactNo;
}
public String getLicenseNo() {
return licenseNo;
}
public void setLicenseNo(String licenseNo) {
this.licenseNo = licenseNo;
}
public List<Vehicle> getAsignedVehicle() {
return asignedVehicle;
}
public void setAsignedVehicle(List<Vehicle> asignedVehicle) {
this.asignedVehicle = asignedVehicle;
}
public CompanyDetails getCompanyDetail() {
return companyDetail;
}
public void setCompanyDetail(CompanyDetails companyDetail) {
this.companyDetail = companyDetail;
}
public void setContactNo(String contactNo) {
this.contactNo = contactNo;
}
}
MAIN TEST CLASS
package com.javarnd.pns.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import com.javarnd.pns.model.CompanyDetails;
import com.javarnd.pns.model.DriverDetail;
import com.javarnd.pns.service.CompanyDetailService;
import com.javarnd.pns.service.DriverDetailService;
public class TestPns {
public static void main(String[] args) {
CompanyDetailService cdService=new CompanyDetailService();
CompanyDetails cd=new CompanyDetails();
List<DriverDetail>ddList=new ArrayList<>();
DriverDetail driver=new DriverDetail();
DriverDetailService dds=new DriverDetailService();
Scanner kb=new Scanner(System.in);
System.out.println("Enter name:");
String cname=kb.nextLine();
driver.setName(cname);
System.out.println("Enter Compnay Id");
long companyId=kb.nextLong();
cd.setCompanyId(companyId);
System.out.println("Enter License:");
String license=kb.next();
driver.setLicenseNo(license);
System.out.println("Enter Contact");
String contact=kb.nextLine();
driver.setContactNo(contact);
ddList.add(driver);
cd.setDriverList(ddList);
driver.setCompanyDetail(cd);
dds.save(driver);
System.out.println("saved");
}
}
And now I tested that from my above main class, it printed the log in which it insert the values in DriverDetail table and update the company_detail table and at last then insert the values in COMPANY_DRIVER_DETAIL table
Finally the console LOG
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
/* insert com.javarnd.pns.model.DriverDetail
*/ insert
into
DriverDetail
(company_id, contact_no, license_no, name, driver_id)
values
(?, ?, ?, ?, ?)
Hibernate: //HERE IT IS UPDATING THE CompanyDetail , MAIKING ALL FIELDS NULL
/* update
com.javarnd.pns.model.CompanyDetails */ update
company_detail
set
company_name=?,
type=?,
conntact_no=?,
email=?,
pan_no=?,
website=?
where
company_id=?
Hibernate:
/* delete collection com.javarnd.pns.model.CompanyDetails.driverList */ delete
from
COMPANY_DRIVER_DETAIL
where
company_id=?
Hibernate:
/* delete collection com.javarnd.pns.model.CompanyDetails.vehicleList */ delete
from
COMPANY_VEHICLE_DETAIL
where
company_id=?
Hibernate:
/* insert collection
row com.javarnd.pns.model.CompanyDetails.driverList */ insert
into
COMPANY_DRIVER_DETAIL
(company_id, driver_id)
values
(?, ?)
After this everything goes fine except that the data corresponding of the particular id in Country_detail table is all NULL, and i don't want to fetch the data on behalf of id and then pass the object to driver.setCompanyDetail(cd); because it somehow degrades the performance, i need to know the way to resist this unnecessary update.
I have data model like below
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import org.hibernate.annotations.DiscriminatorOptions;
#SuppressWarnings("deprecation")
#Entity
#Table
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name="DTYPE", discriminatorType=DiscriminatorType.INTEGER)
#DiscriminatorValue("0")
#DiscriminatorOptions(force=true)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
public Employee() {
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "EMPLOYEE_ID")
private int empID;
private String firstName;
private String lastName;
private Integer age;
private String email;
private String city;
private String phNum;
public String getPhNum() {
return phNum;
}
public void setPhNum(String phNum) {
this.phNum = phNum;
}
public int getEmpID() {
return empID;
}
public void setEmpID(int empID) {
this.empID = empID;
}
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Patient.java
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.validator.constraints.NotEmpty;
#SuppressWarnings("deprecation")
#Entity
#Table
#PrimaryKeyJoinColumn(name = "EMPLOYEE_ID")
#DiscriminatorValue("6")
public class Patient extends Employee {
private static final long serialVersionUID = 1L;
#NotEmpty(message = "DOJ cannot be null")
private String doj;
private String primaryDoctor;
public String getPrimaryDoctor() {
return primaryDoctor;
}
public void setPrimaryDoctor(String primaryDoctor) {
this.primaryDoctor = primaryDoctor;
}
public String getDoj() {
return doj;
}
public void setDoj(String doj) {
this.doj = doj;
}
#OneToMany(cascade = CascadeType.ALL, mappedBy = "patient", fetch = FetchType.LAZY)
private List<Encounter> encounterList;
public List<Encounter> getEncounterList() {
return encounterList;
}
public void setEncounterList(List<Encounter> encounterList) {
this.encounterList = encounterList;
}
}
Hibernate query at runtime
select useraccoun0_.empID as empID1_13_2_, useraccoun0_.EMPLOYEE_ID as EMPLOYEE6_13_2_,
useraccoun0_.fullName as fullName2_13_2_, useraccoun0_.password as password3_13_2_,
useraccoun0_.role as role4_13_2_, useraccoun0_.userName as userName5_13_2_,
employee1_.EMPLOYEE_ID as EMPLOYEE2_2_0_, employee1_.age as age3_2_0_,
employee1_.city as city4_2_0_, employee1_.email as email5_2_0_, employee1_.firstName as firstNam6_2_0_,
employee1_.lastName as lastName7_2_0_, employee1_.phNum as phNum8_2_0_, employee1_4_.doj as doj1_11_0_,
employee1_4_.primaryDoctor as primaryD2_11_0_, employee1_5_.specialization as speciali1_0_0_,
employee1_.DTYPE as DTYPE1_2_0_, encounterl2_.EMPLOYEE_ID as EMPLOYEE4_3_4_,
encounterl2_.EID as EID1_3_4_, encounterl2_.EID as EID1_3_1_, encounterl2_.labTest_testID as labTest_2_3_1_,
encounterl2_.medication_mid as medicati3_3_1_, encounterl2_.EMPLOYEE_ID as EMPLOYEE4_3_1_,
encounterl2_.vitalSign_EID as vitalSig5_3_1_ from UserAccount useraccoun0_
left outer join Employee employee1_ on useraccoun0_.EMPLOYEE_ID=employee1_.EMPLOYEE_ID
left outer join Pharmacist employee1_1_ on employee1_.EMPLOYEE_ID=employee1_1_.EMPLOYEE_ID
left outer join Nurse employee1_2_ on employee1_.EMPLOYEE_ID=employee1_2_.EMPLOYEE_ID
left outer join LabAssistant employee1_3_ on employee1_.EMPLOYEE_ID=employee1_3_.EMPLOYEE_ID
left outer join Patient employee1_4_ on employee1_.EMPLOYEE_ID=employee1_4_.EMPLOYEE_ID
left outer join Doctor employee1_5_ on employee1_.EMPLOYEE_ID=employee1_5_.EMPLOYEE_ID
left outer join Encounter encounterl2_ on employee1_.EMPLOYEE_ID=encounterl2_.EMPLOYEE_ID
where useraccoun0_.empID=4
In this query Discriminator column(DTYPE) is coming and its value is coming as 6. But it is giving me below exception
org.hibernate.WrongClassException: Object [id=null] was not of the specified subclass [com.*.*.Employee]: the class of the given object did not match the class of persistent copy
So not sure why it is giving me this exception and why id is coming as null.
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: