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

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.

Related

Hibernate PostgreSQL OneToOne Relationship Trigger Child Query First

I'm building app to learn Hibernate on PostgreSQL. And I'm currently trying to add variable to database that has OneToOne relationship.
First, I create two tables in my database with schema below. On person_detail table it has primary key that's also foreign key to person table.
Then I created two classes, Person and PersonDetail. PersonDetail is child of Person that has OneToOne relationship. And I use code below to add person with personDetail as attribute.
Person person = new Person(
"Rick",
1.7,
dateFromString("1969-4-2"),
new Date()
);
PersonDetail personDetail =
new PersonDetail("myemail#email.com", "Marley");
person.setPersonDetail(personDetail);
session.beginTransaction();
session.save(person);
session.save(personDetail);
session.getTransaction().commit();
System.out.println(person.toString());
But the problem with code above is that Hibernate execute child query first instead of parent query.
Hibernate: insert into person_detail (address, email) values (?, ?)
And since person still empty, we cannot insert any row to person_detail because it violates foreign key constraint.
Is there a way to solve this?
Thanks!
In case some one want to check how I annotate those two classes, I put the code below.
#Entity
#Table(name="person")
#Data
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#Column(name="height")
private double height;
#Column(name="birth_date")
private Date dateBirth;
#Column(name="last_seen")
private Date lastSeen;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id")
private PersonDetail personDetail;
public Person() {}
public Person(String name, double height, Date dateBirth, Date lastSeen){
this.name = name;
this.height = height;
this.dateBirth = dateBirth;
this.lastSeen = lastSeen;
}
}
#Data
#Entity
#Table(name="person_detail")
public class PersonDetail {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name="email")
private String email;
#Column(name="address")
private String address;
public PersonDetail(){}
public PersonDetail(String email, String address){
this.email = email;
this.address = address;
}
}
I see that you have primary key in table person_details as foreign key to person table, you can use #PrimaryKeyJoinColumn like this:
#Entity
#Table(name="person")
#Data
public class Person {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "height")
private String height;
#OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private PersonDetail personDetail;
public Person() {}
public Person(String name, String height) {
this.name = name;
this.height = height;
}
}
#Data
#Entity
#Table(name="person_detail")
public class PersonDetail {
#Id
#Column(name="id")
private Long id;
#Column(name="email")
private String email;
#OneToOne
#MapsId
#JoinColumn(name = "id", referencedColumnName = "id")
private Person person;
public PersonDetail(){}
public PersonDetail(String email){
this.email = email;
}
}
And if you save your entity, don't forget set Person to PersonDetails:
Person person = new Person("Rick", "1.7");
PersonDetail personDetail = new PersonDetail("myemail#email.com");
personDetail.setPerson(person);
person.setPersonDetail(personDetail);
repository.save(person);

How to use relationships between tables in jpa

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.

How to join three entities in one table using spring jpa?

I am trying to join three entities (table) using spring-jpa into one table using Many-To-Many relationship.
Three classes are :
1] User
2] Resource
3] Privilege
And I want to combine these three entities into one User_Resource_Privilege table
User Entity
package com.****.acl.domain;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
#Entity
public class User {
#Id #GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
#Column(name="user_id", nullable=false, length=40)
private String userId;
#Column(name="user_name", nullable=false, length=45)
private String userName;
#Column(name="first_name", nullable=true, length=45)
private String firstName;
#Column(name="last_name", nullable=true, length=45)
private String lastName;
#Column(name="email", nullable=true, length=50)
private String email;
public User(){
}
public User(String userName, String firstName, String lastName, String email) {
this.userName = userName;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
getter and setters .......
}
Resource Entity
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class Resource {
#Id #GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
#Column(name="resource_id", nullable=false, length=40)
private String resourceId;
#Column(name="resource_name", nullable=false, length=45)
private String name;
#Column(name="resource_type", nullable=false, length=45)
private String type;
public Resource(){
}
public Resource(String name, String type) {
this.name = name;
this.type = type;
}
getter and setter ......
}
Privilege Entity
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class Privilege {
#Id #GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
#Column(name="privilege_id", nullable=false, length=40)
private String privilegeId;
#Column(name="resource_name", nullable=false, length=45)
private String name;
#Column(name="resource_description", nullable=true, length=45)
private String description;
public Privilege(){
}
getters and setters ....
}
Now I want to create one table by joining all the three entities described above.
The join in ER diagram:
Can someone please help me in joining these three tables using Many-To-Many relationship and let me know how to achieve this using spring-jpa and REST ?
Also it will be great if you please explain how to insert data in this "User_Resource_Privilege" table using REST/curl command ?
What you could do is make an embeddable ID and wrap it with the class. You can afterwards even expand this wrapper class to hold other fields.
java geeks example of embedded id
You would get something like
#Embeddable
public class EmbeddedIdClass implements Serializable {
private String userId;
private String resourceId;
private String privilegeId;
// constructors, getters and setters, equals, etc
}
#Entity
public class Wrapper {
#EmbeddedId
private EmbeddedIdClass id;
// constructors, etc
}
Instead of just using the strings in this example, you should use the complete objects and let hibernate (or something like it) do it's stuff. It should only take the id's into the database and do it's magic itself.
edit:
Just wanting to insert the id's as values, but keeping relationships would look something like this
#Entity
public class Wrapper {
#Id
private String id;
private User user;
private Resource resource;
private Privilege privilege;
// constructors
public Wrapper(final User user, final Resource resource, final Privilege privilege) {
this.user = user;
this.resource = resource;
this.privilege = privilege;
}
}

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.

Create separate hibernate search indexes for each subclass

I just started playing around with hibernate search.
How can I solve the following problem.
All my java entities where inherited from a superclass:
#SuppressWarnings("rawtypes")
#MappedSuperclass
#Indexed
public abstract class BaseEntity{
private Integer id;
private Integer jpaVersion;
private Date creaDate;
private Date modDate;
private String creaUser;
private String modUser;
#Id
#Column(name = "ID", unique = true, nullable = false, precision = 22, scale = 0)
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
.....
For example I have to (there are more) subclasses:
#Entity
#Indexed
#Table(name = "BASE_PERSON", schema = "MYSCHEMA")
public class Person extends extends BaseEntity{
private String firstName;
private String lastName;
....
....
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
#Column(name = "LASTNAME", nullable = false, length = 50)
#NotNull
#Size(max=50)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
#Column(name = "FIRSTNAME", length = 50)
#Size(max=50)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
and a second one:
#Entity
#Indexed
#Table(name = "BASE_USER", schema = "MYSCHEMA")
public class User extends extends BaseEntity{
private String userName;
....
....
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
#Column(name = "USERNAME", nullable = false, length = 50)
#NotNull
#Size(max=50)
public String getUserName() {
return this.userName;
}
public void setUserName(String lastName) {
this.UserName = UserName;
}
....
After running the code for creating the whole index, I got three indexes. One more than I expected. The indexes are: BaseEntity, Person and User.
But all Persons and Useres ares stored in the index BaseEntity and not in their own index.
Is there a way to change this, so that all persons are in the index person and all users are in the index users?
Or is this the common behaviour of hibernate search?
Thanks and Regards
LStrike
You'll want to remove the #Indexed from the BaseEntity, you only need that annotation on the subclasses. You can still annotate properties in BaseEntity with #Field to make them appear in the subclass indexes.

Categories