Unable to save data using hibernate.save() - java

I am trying to add Staff object which has staff information, roles and subjects. The code below saves only Staff data not its associated collections data.
I have tried to debug it but didn't understand the issue. The staff object has roles and subjects before saving into database but they are not getting saved in the DB. Surprisingly, the similar code is working while saving Course table data; however, Course does also have collection of Subject class.
It seems to me that Subjects have Course object which may be creating problem, I am not sure why. Please advise how to fix it.
The complete project is available on GitHub(https://github.com/ravinain/practice/tree/master/Java/Spring/SchoolProject)
Staff.java
#Entity
#Table
public class Staff extends Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private double salary;
#OneToMany(mappedBy = "staff", fetch=FetchType.EAGER)
#Cascade({ CascadeType.ALL})
private Set<Role> roles = new HashSet<Role>();
#ManyToMany(mappedBy = "staffs", fetch=FetchType.EAGER)
#Cascade({CascadeType.ALL})
private Set<Subject> subjects = new HashSet<Subject>();
Role.java
#Entity
#Table
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#NotNull
private int id;
private String name;
#ManyToOne
#JoinTable(name = "role_staff", joinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "staff_id", referencedColumnName = "id"))
#JsonIgnore
private Staff staff;
Subject.java
#Entity
#Table
public class Subject implements Comparable<Subject>{
#Id
#Column
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String description;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "subject_staff", joinColumns = #JoinColumn(name = "subject_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "staff_id", referencedColumnName = "id"))
#JsonIgnore
private Set<Staff> staffs = new HashSet<Staff>();
#ManyToMany(mappedBy = "subjects", fetch = FetchType.EAGER)
#Cascade({ CascadeType.DELETE, CascadeType.SAVE_UPDATE })
#JsonIgnore
private Set<Course> courses = new HashSet<Course>();
#ManyToMany(mappedBy = "subjects", fetch = FetchType.EAGER)
#Cascade({ CascadeType.DELETE, CascadeType.SAVE_UPDATE })
#JsonIgnore
private Set<Student> students = new HashSet<Student>();
DAO Code:
public Staff addStaff(Staff staff) {
Session session = sessionFactory.getCurrentSession();
session.save(staff);
return staff;
}
POST Request:
{"name":"New Test","age":22,"gender":"Female","salary":12000,"roles":[{"id":3,"name":"Teacher"}],"subjects":[{"id":1,"description":"Math"},{"id":2,"description":"English"}]}

Related

Is there a way to return user rating of a one book for that user?

I am working on a project, trying to create an AudioBook website. I am stuck on this part and i cant find answers on the internet.
The problem is when i get user, and list of favorite books, each book has list of user rating, from all of the users. And also there is a list of UserRatings that contains all of ratings from that user. I dont want neither.
Basically, is there a way to make it so when i do a search for list of books, every book object contains UserRating(One user rating) from a specific User that is logged in?
#Entity
#Table(name = "user_rating")
public class user_rating {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Integer Id;
#Column
private String rating;
#ManyToOne
#JoinColumn(name = "user_id")
private users user;
#ManyToOne
#JoinColumn(name = "book_id")
private books book;
#Entity
#Table(name = "users")
public class users {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private String name;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "date_of_creation")
private java.sql.Date dateOfCreation;
#Column
private String password;
#JsonManagedReference
#ManyToMany
#JoinTable(
name = "favourites",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id")
)
private Set<books> favourites = new HashSet<>();
#OneToMany(mappedBy ="user")
private List<user_rating> UserRating = new ArrayList<>();
#Entity
#Table(name = "books")
public class books {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private String name;
#Column
private String description;
#Column(name = "date_of_creation")
private java.sql.Date date_of_creation;
#Column
private String text_file;
#JsonBackReference
#ManyToMany(mappedBy = "favourites")
private Set<users> users = new HashSet<>();
#JsonManagedReference
#ManyToMany()
#JoinTable(
name = "book_tags",
joinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "tag_id", referencedColumnName = "id")
)
private List<tags> tags = new ArrayList<>();
#OneToOne
#PrimaryKeyJoinColumn
private audio_file audioFile;
#OneToMany(mappedBy = "book")
private List<user_rating> UserRatings = new ArrayList<>();

java manytomany mapping not creating

I created two simple entities for trying out the java persistence manytomany mapping. But whatever I try, the jointable won't be populated with a mapping and remains empty.
UserClass:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#ManyToMany(targetEntity = Order.class ,fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "users_orders",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "order_id", referencedColumnName = "id")
)
#JsonIgnoreProperties(value = "orderUsers")
private Set<Order> userOrders = new HashSet<>();
}
OrderClass:
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#ManyToMany(mappedBy = "userOrders", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnoreProperties(value = "userOrders")
private Set<User> orderUsers = new HashSet<>();
}
I added Getter/Setter/Constructor via Lombok.
Create and save an user. Create an order, add the user and save it. But still the jointable remains empty.
Any ideas?

Hibernate Criteria Api with Inner Join and Many to Many

I'm new with Hibernate and Criteria Query.
How can I implement it with Hibernate Criteria Object?
SELECT stateslocalization.StateId, stateslocalization.localization AS name
FROM processstate
Join states ON states.id = processstate.StateId
JOIN stateslocalization ON stateslocalization.StateId = states.id
WHERE processstate.ProcessId = 38 and processstate.StateId = states.id AND stateslocalization.StateId = states.id
Entities:
Process:
#Entity
#Table(name = "processes")
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
#JoinTable(
name = "processstate",
joinColumns = {#JoinColumn(name = "ProcessId")},
inverseJoinColumns = {#JoinColumn(name = "StateId")}
)
private Set<State> states;
//getters and setters.....
}
State:
#Entity
#Table(name = "states")
public class State {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
private String name;
#ManyToMany(mappedBy = "states", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Process> processes;
#OneToOne(mappedBy = "state")
private StateLocalization stateLocalization;
//getters and setters.....
}
StateLocalization:
#Entity
#Table(name = "stateslocalization")
public class StateLocalization {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "StateId", referencedColumnName = "id")
private State state;
private String localization;
//getters and setters.....
}
I did it with native query but I don't know how I can implement it to Hibernate Criteria, because I don't have entity processstate (it's only table).

Hibernate two parents one child mapping

I have following scenario: There are companies and employees. Each company has a set of employees. Each employee can work for several companies. So I implemented following relationships:
Company.class:
#JoinTable(name = "company_employee", joinColumns = #JoinColumn(name = "company_id") , inverseJoinColumns = #JoinColumn(name = "employee_id") )
#ManyToMany(fetch = FetchType.LAZY)
private List<Employee> employees;
Employee.class:
#JoinTable(name = "company_employee", joinColumns = #JoinColumn(name = "employee_id") , inverseJoinColumns = #JoinColumn(name = "company_id") )
#ManyToMany(fetch = FetchType.LAZY)
private List<Company> companies;
Obviously, to work for several companies, each employee should have several not overlapping schedules assigned for each company he or she works.
Also, there should be a list of schedules for each combination Company-Employee, as sometimes old schedule expires, and new schedule becomes effective.
So I also have Schedule.class, which is supposed to have child to parent #ManyToOne relationships both to Company and Employee, and should work following way: each Schedule, and thus, List<Schedule> should correspond to exactly one combination of Company and Employee instances.
How to implement this relationship?
Update 1
I only have in mind adding #OneToMany Schedule relationship to each Company and Employee, but then I need to put instances of Schedule both to Company and Employee each time, and this way just don't look right, also it's not obvious for me now how to fetch it back.
So any help will be appreciated.
This post was updated to show real-life scenario I have, not just generic Entity1, Entity2, Entity3 names for classes.
Update 2
I accepted the answer, but I cannot use it if Schedule contain Lists.
According to my plan, Schedule should contain List<Vacation> to know the set of Vacations over a year, and List of Days, each of which shows start of particular week day, break, and end of this day. Those Days are also unique for each Schedule instance.
It was supposed to be something like below, but obviously now I don't have schedule_id, so how to connect those lists to Schedule?
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "schedule_id")
private List<Vacation> vacations;
#JoinTable(name = "schedule_week", joinColumns = #JoinColumn(name = "schedule_id") , inverseJoinColumns = #JoinColumn(name = "day_id") )
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Day> week;
How to include those lists right?
I would like to suggest the following solution.
An embeddable class that contains the Company and Employee for a particular schedule.
#Embeddable
public class ScheduleOwner implements Serializable{
#MapsId("id")
#ManyToOne(cascade = CascadeType.ALL)
Company c;
#MapsId("id")
#ManyToOne(cascade = CascadeType.ALL)
Employee e;
}
The Schedule class is embedding a ScheduleOwner instance.
#Entity
public class Schedule {
#EmbeddedId
ScheduleOwner owner;
String description;
}
The Company and Employee classes(no change done to them)
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#JoinTable(name = "company_employee", joinColumns = #JoinColumn(name = "company_id") , inverseJoinColumns = #JoinColumn(name = "employee_id") )
#ManyToMany(fetch = FetchType.LAZY)
private List<Employee> employees;
}
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#JoinTable(name = "company_employee", joinColumns = #JoinColumn(name = "employee_id") , inverseJoinColumns = #JoinColumn(name = "company_id") )
#ManyToMany(fetch = FetchType.LAZY)
private List<Company> companies;
}
UPDATE 1
Below is how you could save and fetch results.
Employee e1 = new Employee();
Company c1 = new Company();
c1.employees.add(e1);
e1.companies.add(c1);
ScheduleOwner so = new ScheduleOwner();
so.c = c1;
so.e = e1;
Schedule s = new Schedule();
s.owner = so;
session.save(c1);
session.save(e1);
session.save(s);
// below query will fetch from schedule, where company id = 9
Schedule ss = (Schedule) session.createQuery("From Schedule sh where sh.owner.c.id = 9").uniqueResult();
UPDATE 2
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#JoinTable(name = "company_employee", joinColumns = #JoinColumn(name = "company_id", referencedColumnName="id")
, inverseJoinColumns = #JoinColumn(name = "employee_id", referencedColumnName="id"))
#ManyToMany(fetch = FetchType.LAZY)
List<Employee> employees = new ArrayList<>();
String name;
}
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "employees")
List<Company> companies = new ArrayList<>();
String name;
}
#Entity
public class Schedule {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
int schedule_id;
#ManyToOne
#JoinColumn(name = "company_id", insertable = false, updatable = false)
private Company company;
#ManyToOne
#JoinColumn(name = "employee_id", insertable = false, updatable = false)
private Employee employee;
String description;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "schedule")
List<Vacation> vacations;
}
#Entity
public class Vacation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int vacation_id;
#ManyToOne
#JoinColumn(name = "schedule_id" )
Schedule schedule;
#OneToMany(mappedBy = "vacation")
List<Day> days;
}
Day entity directly relates to Vacation. Not to Schedule.
#Entity
public class Day {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
#JoinColumn(name = "vacation_id")
Vacation vacation;
}
Hope this helps.

Spring JPA: When I delete an entity, the entities related are deleted too

First of all, thanks for be interested in this question.
The scenario is like that: there is an entity Usuario (user) which has several Role. When I delete an User, all Roles related are deleted too.
The code for Role is:
#Entity
#Table(name = "marte_role")
#XmlRootElement
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String nombre;
#ManyToMany(
fetch = FetchType.EAGER,
targetEntity = Usuario.class,
cascade = { CascadeType.ALL })
#JoinTable(
name = "marte_usuario_role",
joinColumns = { #JoinColumn(name = "role_id") },
inverseJoinColumns = { #JoinColumn(name = "usuario_id") })
#JsonIgnore
private List<Usuario> users = new ArrayList<Usuario>();
... Getters/setters/builders...
And the code for Usuario is:
#Entity
#Table(name = "marte_usuario")
#XmlRootElement
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
private String password;
private String email;
private boolean enabled;
#ManyToMany(
fetch = FetchType.EAGER
, targetEntity = Role.class
, cascade = { CascadeType.ALL })
#JoinTable(
name = "marte_usuario_role"
, joinColumns = { #JoinColumn(name = "usuario_id") }
, inverseJoinColumns = { #JoinColumn(name = "role_id") })
private List<Role> roles = new ArrayList<Role>();
#Transient
private int numRoles;
It seems to me that is related with CascadeType.ALL. I've tested with CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE, instead of CascadeType.ALL and then the entity is NOT deleted.
Does anyone know what I am doing wrong?
Thanks in advance for your answers.
CascadeType.ALL include also CascadeType.REMOVE, that's why your entities are removed with this annotation.
You're not doing anything wrong. You specify CascadeType.ALL, which means all operations, including delete, are cascaded to related entities. If you don't want that to happen, don't use CascadeType.ALL.
Solved!
The answers provided are both correct: remove CascadeType.ALL, but just in the Role entity. With this change is possible to remove an Usuario, without deleting all the Role related.
#Entity
#Table(name = "marte_role")
#XmlRootElement
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String nombre;
#ManyToMany(
fetch = FetchType.EAGER,
targetEntity = Usuario.class
)
#JoinTable(
name = "marte_usuario_role",
joinColumns = { #JoinColumn(name = "role_id") },
inverseJoinColumns = { #JoinColumn(name = "usuario_id") })
#JsonIgnore
private List<Usuario> users = new ArrayList<Usuario>();
...
Thanks!

Categories

Resources