Spring data repositories - performance issue - spring

I'm using Spring , JPArepostories and hibernate, to save some entities to database.
My entities :
Users:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#Column(name = "CARDID",unique=true)
private String cardId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="SUPPLIERUSERID", nullable = true)
#JsonIgnore
private SupplierUser supplierUser;
#Column(name = "NAME")
private String name;
#Column(name = "SURENAME")
private String sureName;
#Column(name = "ACTIVE")
private Boolean active;
#Column(name = "SMS")
private String sms;
#Column(name = "EMAIL")
private String email;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Box> boxList = new ArrayList<Box>();
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Notification> notificationList = new ArrayList<Notification>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public SupplierUser getSupplierUser() {
return supplierUser;
}
public void setSupplierUser(SupplierUser supplierUser) {
this.supplierUser = supplierUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSureName() {
return sureName;
}
public void setSureName(String sureName) {
this.sureName = sureName;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public String getSms() {
return sms;
}
public void setSms(String sms) {
this.sms = sms;
}
public List<Box> getBoxList() {
return boxList;
}
public void setBoxList(List<Box> boxList) {
this.boxList = boxList;
}
public List<Notification> getNotificationList() {
return notificationList;
}
public void setNotificationList(List<Notification> notificationList) {
this.notificationList = notificationList;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Users have boxes:
#Entity
#Table(name = "boxes")
public class Box {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="USERID", nullable = true)
#JsonIgnore
private User user;
#Column(name = "BOXNUMBER",unique=true)
private int boxNumber;
#Column(name = "MODBUSADDRESS")
private int modbusAddress;
#Column(name = "MODBUSREGISTER")
private int modbusRegister;
#Column(name = "STATE")
private String state;
#OneToMany(mappedBy = "box", fetch =FetchType.EAGER,cascade = CascadeType.ALL)
private List<Transaction> transactionsList = new ArrayList<Transaction>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getModbusAddress() {
return modbusAddress;
}
public void setModbusAddress(int modbusAddress) {
this.modbusAddress = modbusAddress;
}
public int getModbusRegister() {
return modbusRegister;
}
public void setModbusRegister(int modbusRegister) {
this.modbusRegister = modbusRegister;
}
public List<Transaction> getTransactionsList() {
return transactionsList;
}
public void setTransactionsList(List<Transaction> transactionsList) {
this.transactionsList = transactionsList;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getBoxNumber() {
return boxNumber;
}
public void setBoxNumber(int boxNumber) {
this.boxNumber = boxNumber;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Boxes have transactions:
#Entity
#Table(name = "transactions")
public class Transaction {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="BOXID", nullable = true)
#JsonIgnore
private Box box;
#Column(name = "TYPE")
private String type;
#Column(name = "SUPPLIERUSERCARDID")
private String supplierUserCardId;
#Column(name = "DATE")
#Temporal(TemporalType.TIMESTAMP)
private Date date;
#OneToMany(mappedBy = "transaction", fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private List<Notification> notificationsList = new ArrayList<Notification>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Box getBox() {
return box;
}
public void setBox(Box box) {
this.box = box;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getSupplierUserCardId() {
return supplierUserCardId;
}
public void setSupplierUserCardId(String supplierUserCardId) {
this.supplierUserCardId = supplierUserCardId;
}
public List<Notification> getNotificationsList() {
return notificationsList;
}
public void setNotificationsList(List<Notification> notificationsList) {
this.notificationsList = notificationsList;
}
}
And transaction have notifications (notification refer as well to user):
#Entity
#Table(name = "notifications")
public class Notification {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="TRANSACTIONID", nullable = true)
#JsonIgnore
private Transaction transaction;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name ="USERID", nullable = true)
#JsonIgnore
private User user;
#Column(name = "TYPE")
private String type;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CREATED")
private Date created;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "SENDED")
private Date sended;
#Column(name = "RETRIES")
private Long retries;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getSended() {
return sended;
}
public void setSended(Date sended) {
this.sended = sended;
}
public Long getRetries() {
return retries;
}
public void setRetries(Long retries) {
this.retries = retries;
}
public Transaction getTransaction() {
return transaction;
}
public void setTransaction(Transaction transaction) {
this.transaction = transaction;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
And my question is - what I'm doing wrong, because following method for list with 150 boxes inside takes about 20 seconds to finish.
public void changeBoxOwners(ArrayList<Box> boxList){
String id = theSoftwareCore.getSupplierUser().getCardId();
ArrayList<Box> boxToSave = new ArrayList<Box>();
for (Box box : boxList){
Box existingBox = theSoftwareCore.boxServiceImp.findByBoxNumber(box.getBoxNumber());
existingBox.setState("full");
User user = theSoftwareCore.userServiceImp.findOneByCardId(box.getUser().getCardId());
//deleting not sent notifications
for (Transaction trans : existingBox.getTransactionsList()){
for (Notification notif: trans.getNotificationsList()){
if (notif.getSended()==null){
notif.setSended(new Date(0));
}
}
}
Transaction transaction = new Transaction();
transaction.setType("in");
transaction.setSupplierUserCardId(id);
transaction.setDate(new Date());
transaction.setBox(existingBox);
Notification notification = new Notification();
notification.setCreated(new Date());
notification.setType("smsTakeYourStaff");
notification.setTransaction(transaction);
notification.setUser(user);
existingBox.setUser(user);
transaction.getNotificationsList().add(notification);
existingBox.getTransactionsList().add(transaction);
boxToSave.add(existingBox);
}
System.out.println("Start saving" + new Date());
theSoftwareCore.boxServiceImp.saveAll(boxToSave);
System.out.println("End " + new Date());
}
Thanks for your time in advance.

Related

I cannot remove the association in Many To Many bidirectional hibernate

I can't delete the association in the courses_student table of course and student when trying to delete a course, even if I want to cascade delete it does not work for me since there is a foreign key in courses_student, I don't know what the problem is.
I have also tried to remove the association in the courses_student table doing a update.but nothing happened.
DAO
#Override
public boolean deleteCourse(int id) {
Session currentSession = entityManager.unwrap(Session.class);
Courses course = currentSession.load(Courses.class, id);
for(Student student : course.getEstudiantes()) {
course.removeStudent(student);
}
currentSession.delete(course);
if(course.getId() == null)
return true;
else
return false;
}
Courses entity
#Entity
#Table(name = "courses")
public class Courses {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#Column
private String nombre;
#Column
private String descripcion;
#ManyToMany(mappedBy = "courses")
private Set<Student> Estudiantes = new HashSet<Student>();
public Courses() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public Set<Student> getEstudiantes() {
return Estudiantes;
}
public void setEstudiantes(Set<Student> estudiantes) {
Estudiantes = estudiantes;
}
public void removeStudent(Student student) {
this.Estudiantes.remove(student);
student.getCourses().remove(this);
}
}
Student entity
#Entity
#Table(name = "students")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#Column
private String nombre;
#Column
private String apellido;
#Column
private String dni;
#ManyToMany(fetch=FetchType.LAZY,
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
#JoinTable(
name="courses_students",
joinColumns=#JoinColumn(name="id_student"),
inverseJoinColumns=#JoinColumn(name="id_course")
)
private Set<Courses> courses = new HashSet<Courses>();
public Student() {
}
public Student(String nombre, String apellido, String dni) {
this.nombre = nombre;
this.apellido = apellido;
this.dni = dni;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public Set<Courses> getCourses() {
return courses;
}
public void setCourses(Set<Courses> courses) {
this.courses = courses;
}
}
EDIT:
apparently it works for me, trying to update since owner side.
#Override
public boolean deleteCourse(int id) {
Session currentSession = entityManager.unwrap(Session.class);
Courses course = currentSession.load(Courses.class, id);
for(Student student : course.getEstudiantes()) {
student.removeCourse(course);
}
currentSession.update(course);
if(course.getId() == null)
return true;
else
return false;
}
It seems to me that you are missing a cascade configuration of your #ManyToMany annotation on Courses which is actually the one you are updating / deleting. Try the following:
#ManyToMany(mappedBy = "courses", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Student> Estudiantes = new HashSet<Student>();
Also, given that you have a bi-directional relationship, you should also remove the Course from each Student courses property.

Error mapping OneToMany or ManyToOne unmapped class

I have this problem :
Error creating bean with name 'ICustomerDao' defined in com.biblio.fr.biblio.repository.ICustomerDao defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.biblio.fr.biblio.entite.Book.loans[com.biblio.fr.biblio.entite.Loan]
this is my code :
#Entity
#Table(name = "BOOK")
public class Book {
private Integer id;
private String title;
private String isbn;
private LocalDate releaseDate;
private LocalDate registerDate;
private Integer totalExamplaries;
private String author;
private Category category;
Set<Loan> loans = new HashSet<Loan>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "BOOK_ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "TITLE", nullable = false)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "ISBN", nullable = false, unique = true)
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
#Column(name = "RELEASE_DATE", nullable = false)
public LocalDate getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(LocalDate releaseDate) {
this.releaseDate = releaseDate;
}
#Column(name = "REGISTER_DATE", nullable = false)
public LocalDate getRegisterDate() {
return registerDate;
}
public void setRegisterDate(LocalDate registerDate) {
this.registerDate = registerDate;
}
#Column(name = "TOTAL_EXAMPLARIES")
public Integer getTotalExamplaries() {
return totalExamplaries;
}
public void setTotalExamplaries(Integer totalExamplaries) {
this.totalExamplaries = totalExamplaries;
}
#Column(name = "AUTHOR")
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
#ManyToOne(optional = false)
#JoinColumn(name = "CAT_CODE", referencedColumnName = "CODE")
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
// #OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.book", cascade =
// CascadeType.ALL)
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk", cascade = CascadeType.ALL)
public Set<Loan> getLoans() {
return loans;
}
public void setLoans(Set<Loan> loans) {
this.loans = loans;
}
}
public class Loan implements Serializable {
private static final long serialVersionUID = 144293603488149743L;
private LoanId pk = new LoanId();
private LocalDate beginDate;
private LocalDate endDate;
private LoanStatus status;
#EmbeddedId
public LoanId getPk() {
return pk;
}
public void setPk(LoanId pk) {
this.pk = pk;
}
#Column(name = "BEGIN_DATE", nullable = false)
public LocalDate getBeginDate() {
return beginDate;
}
public void setBeginDate(LocalDate beginDate) {
this.beginDate = beginDate;
}
#Column(name = "END_DATE", nullable = false)
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
#Enumerated(EnumType.STRING)
#Column(name = "STATUS")
public LoanStatus getStatus() {
return status;
}
public void setStatus(LoanStatus status) {
this.status = status;
}
}
#Embeddable
public class LoanId implements Serializable {
private static final long serialVersionUID = 3912193101593832821L;
private Book book;
private Customer customer;
private LocalDateTime creationDateTime;
public LoanId() {
super();
}
public LoanId(Book book, Customer customer) {
super();
this.book = book;
this.customer = customer;
this.creationDateTime = LocalDateTime.now();
}
#ManyToOne
public Book getBook() {
return book;
}
public void setBook(Book bbok) {
this.book = bbok;
}
#ManyToOne
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
#Column(name = "CREATION_DATE_TIME")
public LocalDateTime getCreationDateTime() {
return creationDateTime;
}
public void setCreationDateTime(LocalDateTime creationDateTime) {
this.creationDateTime = creationDateTime;
}
}
#Table(name = "CUSTOMER")
public class Customer {
private Integer id;
private String firstName;
private String lastName;
private String job;
private String address;
private String email;
private LocalDate creationDate;
Set<Loan> loans = new HashSet<Loan>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "CUSTOMER_ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "FIRST_NAME", nullable = false)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "LAST_NAME", nullable = false)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "JOB")
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
#Column(name = "ADDRESS")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
#Column(name = "EMAIL", nullable = false, unique = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "CREATION_DATE", nullable = false)
public LocalDate getCreationDate() {
return creationDate;
}
public void setCreationDate(LocalDate creationDate) {
this.creationDate = creationDate;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.customer", cascade = CascadeType.ALL)
public Set<Loan> getLoans() {
return loans;
}
public void setLoans(Set<Loan> loans) {
this.loans = loans;
}
}
public class Category {
public Category() {
}
public Category(String code, String label) {
super();
this.code = code;
this.label = label;
}
private String code;
private String label;
#Id
#Column(name = "CODE")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Column(name = "LABEL", nullable = false)
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
#Repository
public interface ICategoryDao extends JpaRepository<Category, Integer> {
}
public interface ICustomerDao extends JpaRepository<Customer, Integer> {
public Customer findCustomerByEmailIgnoreCase(String email);
public List<Customer> findCustomerByLastNameIgnoreCase(String lastName);
}
I can't see where is the problem of my oneTomany annotation
Anyone can, i help me.

Not null reference a null or transient value

So i am trying to achieve oneToone relationship between two entity classes.First class is a customer entity class which have two foreign keys buyer_id and seller_id.So what i want initially is that when the user fills the initial credentials in the website the buyer_id and seller_id field should be null and after the user fills the required information for the buyer or seller i will update the row of the corresponding customer and add the buyer_id and seller_id.But when i try to create a customer entry i am getting this error that buyer_id cannot be null?
This is my customer table
#Entity
#Table(name = "Customer")
public class Customer {
public enum Status{
ACTIVE,
IN_ACTIVE
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#OneToOne(fetch = FetchType.LAZY,optional = true,cascade=CascadeType.ALL)
#JoinColumn(name = "seller_id",nullable = true,referencedColumnName = "id",updatable = true)
#Basic(optional = true)
private Seller seller_id;
#OneToOne(fetch=FetchType.LAZY,optional = true,cascade=CascadeType.ALL)
#JoinColumn(name = "buyer_id", nullable = true,referencedColumnName="id",updatable = true)
#Basic(optional = true)
private Buyer buyer_id;
#OneToOne(fetch=FetchType.LAZY,optional = false,cascade = CascadeType.ALL)
#JoinColumn(name = "user_id",nullable = false,unique = true,referencedColumnName = "id")
private User user_id;
public Buyer getBuyer_id() {
return buyer_id;
}
public void setBuyer_id(Buyer buyer_id) {
this.buyer_id = buyer_id;
}
#Column(name = "Name")
String name;
#Enumerated(EnumType.STRING)
#Column(name = "Status")
private Status status;
public Customer(String name,Status status){
this.name=name;
this.status = status;
}
public Customer(){
}
public Seller getSeller_id() {
return seller_id;
}
public void setSeller_id(Seller seller_id) {
this.seller_id = seller_id;
}
public User getUser_id() {
return user_id;
}
public void setUser_id(User user_id) {
this.user_id = user_id;
}
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 User getUser() {
return user_id;
}
public void setUser(User user) {
this.user_id = user;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
This is my buyer table
#Entity
#Table(name="Buyer")
public class Buyer {
#Id
#Column(name = "id") private long id;
#Column(name = "GSTIN")
String GSTIN;
#Column(name = "Legal_Document")
#Lob
private byte[] legalDocument;
#OneToOne(fetch=FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "buyer_id")
#JsonIgnore
private Customer customer;
#Column(name = "Authorized_person_name")
String authorized_person_name;
#Column(name = "Authorized_person_email")
String authorized_person_email;
}
This is my seller table
#Entity
#Table(name = "Seller")
public class Seller {
#Id
#Nullable
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "GSTIN")
private String GSTIN;
#Column(name = "GST_Document")
#Lob
private byte[] gst_document;
#OneToOne(fetch=FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "seller_id")
#JsonIgnore
private Customer customer;
// #OneToOne(fetch = FetchType.LAZY,
// cascade = CascadeType.ALL,
// mappedBy = "sellerId")
// #JsonIgnore
// private PickupAddress pickupAddress;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
public String getGSTIN() {
return GSTIN;
}
public void setGSTIN(String GSTIN) {
this.GSTIN = GSTIN;
}
public byte[] getGst_document() {
return gst_document;
}
public void setGst_document(byte[] gst_document) {
this.gst_document = gst_document;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

POST request with Many-to-many relationship in Spring Data REST

I'm trying to add a movie to MySQL database, here's my database schema:
Movie(id, name)
Genre(id, name)
Movie_genre(id_movie, id_genre)
And here's my model classes:
Movie.ts
public class Movie {
private Short id;
private String name;
private List<MovieGenre> movieGenres;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
public Short getId() {
return id;
}
public void setId(Short id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 100)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "movie")
public List<MovieGenre> getMovieGenres() {
return movieGenres;
}
public void setMovieGenres(List<MovieGenre> movieGenres) {
this.movieGenres = movieGenres;
}
}
Genre.ts
public class Genre {
private Short id;
private String name;
private List<MovieGenre> movieGenres;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
public Short getId() {
return id;
}
public void setId(Short id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 15)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "genre")
#JsonIgnore
public List<MovieGenre> getMovieGenres() {
return movieGenres;
}
public void setMovieGenres(List<MovieGenre> movieGenres) {
this.movieGenres = movieGenres;
}
}
MovieGenre.ts ( that model stands for the generated table )
public class MovieGenre {
private MovieGenrePK id;
private Movie movie;
private Genre genre;
#EmbeddedId
#JsonIgnore
public MovieGenrePK getId() {
return id;
}
public void setId(MovieGenrePK id) {
this.id = id;
}
#MapsId("movieId")
#ManyToOne
#JoinColumn(name = "movie_id", referencedColumnName = "id", nullable = false)
#JsonIgnore
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
#MapsId("genreId")
#ManyToOne
#JoinColumn(name = "genre_id", referencedColumnName = "id", nullable = false)
public Genre getGenre() {
return genre;
}
public void setGenre(Genre genre) {
this.genre = genre;
}
}
and because we have composite key in the last model, we need a class for that :
public class MovieGenrePK implements Serializable {
private Short movieId;
private Short genreId;
#Column(name = "movie_id", nullable = false)
public Short getMovieId() {
return movieId;
}
public void setMovieId(Short movieId) {
this.movieId = movieId;
}
#Column(name = "genre_id", nullable = false)
public Short getGenreId() {
return genreId;
}
public void setGenreId(Short genreId) {
this.genreId = genreId;
}
}
So I'm trying to add a movie with genres by making a post request, first i made a post request for adding a movie and another one for adding a genre, that's works fine, now i need to associate a genre to a movie.
I tried the following:
I made a POST request to the following endpoint: http://localhost:8080/api/movieGenres with application/json header and with the following body:
{
"movie": "http://localhost:8080/api/movies/6",
"genre": "http://localhost:8080/api/genres/1"
}
but i got the error:
{
"timestamp": "2018-08-22T21:10:30.830+0000",
"status": 500,
"error": "Internal Server Error",
"message": "NullPointerException occurred while calling setter of com.movies.mmdbapi.model.MovieGenrePK.genreId; nested exception is org.hibernate.PropertyAccessException: NullPointerException occurred while calling setter of com.movies.mmdbapi.model.MovieGenrePK.genreId",
"path": "/api/movieGenres"
}
You have to instatiate MovieGenrePK, change:
public class MovieGenre {
private MovieGenrePK id;
}
to
public class MovieGenre {
private MovieGenrePK id = new MovieGenrePK();
}

Lazy fetch elements

I'm fetching Company along with productSLA using join fetch query, since the Company has userlist and it doesn't get initialized. Therefore at the time when i send response using responseentity.ok it throws lazy init exception. I don't want user list for that purpose is there any way i can send it to front end without getting lazy init exception some one suggested me to do this using dto.
I am using angular on front end. When i was using jsp i never faced this kind of problem.
#Entity
#Table(name = "USER_TABLE")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch=FetchType.EAGER)
private List<Ticket> raisedTickets;
#NotNull
#Column(unique = true)
#Email(message = "Invalid Email")
private String email;
#NotNull
#Column
#Length(min = 4, max = 12, message = "First name must be between 4 to 12 character long")
private String firstName;
#NotNull
#Column
#Length(min = 4, max = 12, message = "Last name must be between 4 to 12 character long")
private String lastName;
#NotNull
#Column
#Length(min = 8, max = 100, message = "Password must be 4 to 12 character long")
private String password;
#NotNull
#Column
#Length(min = 3, max = 30, message = "Company Name must be between 3 to 12 character long")
private String companyName;
#Column(name = "USER_ROLE")
#Enumerated(EnumType.STRING)
private UserRolesEnum userRole;
#ManyToOne
#JoinColumn(name = "COMPANY_ID", nullable = false)
#NotNull
private Company company;
#OneToMany(mappedBy="user", cascade=CascadeType.ALL)
private List<ProductAssociated> productAssociatedList=new ArrayList<ProductAssociated>();
public User() {
}
public User(String firstName, String lastName, String email, String password, String companyName,
UserRolesEnum role) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.companyName = companyName;
this.userRole = role;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer id) {
this.userId = id;
}
public List<Ticket> getRaisedTickets() {
return raisedTickets;
}
public void setRaisedTickets(List<Ticket> raisedTickets) {
this.raisedTickets = raisedTickets;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public UserRolesEnum getUserRole() {
return userRole;
}
public void setUserRole(UserRolesEnum userRole) {
this.userRole = userRole;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public List<ProductAssociated> getProductAssociatedList() {
return productAssociatedList;
}
public void setProductAssociatedList(List<ProductAssociated> productAssociatedList) {
this.productAssociatedList = productAssociatedList;
}
public void addProductAssociated(ProductAssociated productAssociated) {
productAssociatedList.add(productAssociated);
productAssociated.setUser(this);
}
#Entity
#Table(name="PRODUCT_SLA")
public class ProductSLA {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="SLA_ID")
private Integer slaId;
#NotNull
#Column(name="RESPONSE_TIME")
private int responseTime;
#Column(name="RESOLVE_TIME")
private int resolveTime;
#NotNull
#Column(name="PRIORITY")
#Enumerated(EnumType.STRING)
private PriorityEnum priority;
#ManyToOne
#JoinColumn(name="COMPANY_ID", nullable = false)
private Company company;
#ManyToOne
#JoinColumn(name="PRODUCT_ID", nullable = false)
private Product product;
public ProductSLA() {
super();
}
public ProductSLA(Integer slaId, int responseTime, int resolveTime, PriorityEnum priority) {
super();
this.slaId = slaId;
this.responseTime = responseTime;
this.resolveTime = resolveTime;
this.priority = priority;
}
public Integer getSlaId() {
return slaId;
}
public void setSlaId(Integer slaId) {
this.slaId = slaId;
}
public int getResponseTime() {
return responseTime;
}
public void setResponseTime(int responseTime) {
this.responseTime = responseTime;
}
public int getResolveTime() {
return resolveTime;
}
public void setResolveTime(int resolveTime) {
this.resolveTime = resolveTime;
}
public PriorityEnum getPriority() {
return priority;
}
public void setPriority(PriorityEnum priority) {
this.priority = priority;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
#Entity
#Table(name = "COMPANY_TABLE")
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "COMPANY_ID")
private Integer companyId;
#NotNull
#Column(name = "COMPANY_NAME", unique = true)
private String companyName;
#NotNull
#Column(name = "ADDRESS_LINE1")
private String addressLine1;
#Column(name = "ADDRESS_LINE2")
private String addressLine2;
#NotNull
#Column(name = "CITY")
private String city;
#NotNull
#Column(name="STATE_NAME")
private String state;
#NotNull
#Column(name = "COUNTRY")
private String country;
#NotNull
#Column(name = "PHONE")
private String phone;
#NotNull
#Column(name = "POSTAL_CODE")
private String postalCode;
#NotNull
#Column(name = "COMPANY_WEBSITE")
private String companyWebsite;
#OneToMany( mappedBy = "company", cascade = CascadeType.ALL)
private List<User> userList = new ArrayList<User>();
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
private List<ProductSLA> productSLAList = new ArrayList<ProductSLA>();
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval=true)
private List<AccessLevel> accessLevelList=new ArrayList<AccessLevel>();
public Company() {
super();
}
public Company(Integer companyId, String companyName, String addressLine1, String addressLine2, String city,
String state, String country, String phone, String postalCode, String companyWebsite) {
super();
this.companyId = companyId;
this.companyName = companyName;
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.city = city;
this.state = state;
this.country = country;
this.phone = phone;
this.postalCode = postalCode;
this.companyWebsite = companyWebsite;
}
public Integer getCompanyId() {
return companyId;
}
public void setCompanyId(Integer companyId) {
this.companyId = companyId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
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) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCompanyWebsite() {
return companyWebsite;
}
public void setCompanyWebsite(String companyWebsite) {
this.companyWebsite = companyWebsite;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void addUser(User user) {
userList.add(user);
user.setCompany(this);
}
public List<ProductSLA> getProductSLAList() {
return productSLAList;
}
public void setProductSLAList(List<ProductSLA> productSLAList) {
this.productSLAList = productSLAList;
}
public void addProductSLA(ProductSLA productSLA) {
productSLAList.add(productSLA);
productSLA.setCompany(this);
}
public List<AccessLevel> getAccessLevelList() {
return accessLevelList;
}
public void setAccessLevelList(List<AccessLevel> accessLevelList) {
this.accessLevelList = accessLevelList;
}
public void addAccessLevel(AccessLevel accessLevel) {
accessLevelList.add(accessLevel);
accessLevel.setCompany(this);
}
}
edit
i found solutions but i am confused which one to use and how to use, because there are many solutions there.
Avoid Jackson serialization on non fetched lazy objects
Assuming your hibernate session is closed already in the controller (which is a fair assumption to make since we don't want to expose our hibernate sessions outside spring/hibernate layer) you will run into this type of problem if you try to access a collection which was not loaded when it was inside the session.
Alright!
I'm also assuming that you are returning a one or collection of "hibernate managed entities" as opposed to DTOs. What I'm sensing is that when that entity is converted into JSON all the getters are called by underlying framework unless they are marked 'ignore' (or something like that). OR may be your UI is calling userList at which point it's throwing exception since a proxy was returned by hibernate.
Regardless, it's better to return a DTO and populate it however way you like. There are various reasons why returning a DTO (or a collection of DTOs) is preferred over returning an entity.
To resolve this problem, i've used http message converter,
Application Configuration looks like this:
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
and
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
Dependency Required
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.7</version>
</dependency>
There is a dirty solution also for this,if you are willing to modify every getters:
jackson 2 object to json ignore lazy loading

Resources