Mapping between two classes with JpaRepository SpringBoot - java

Well I have a class Service and a class Employee
Service.java
import lombok.Data;
import javax.persistence.*;
#Data
#Table(name = "services")
#Entity
public class ServiceResource {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String date;
private String longitude;
private String latitude;
#ManyToOne
#JoinColumn(name="employee_id")
private EmployeeResource employee;
}
Employee.java
import lombok.Data;
import javax.persistence.*;
#Data
#Table(name = "employees")
#Entity
public class EmployeeResource {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String longitude;
private String latitude;
}
Now I'd like to build my application that the mapping between service and employee is done with JPA. Is that even possible and how?

Add this to your EmployeeResource Entity:
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
private List<ServiceResource> serviceList;
and in ServiceResource, modify the join column like this:
#ManyToOne
#JoinColumn(name="employee_id", referencedColumnName = "id")
private EmployeeResource employee;

Related

Spring ModelMapping error appeared when I try to convert Post to PostDTO,if I replace #Data annotation with #Getter, #Setter, it works perfectly

package com.springboot.blog.entity;
import lombok.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "posts")
public class Post {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "description", nullable = false)
private String description;
#Column(name = "content", nullable = false)
private String content;
#OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Comment> comments = new HashSet<>();
}
Here is the Post class
package com.springboot.blog.payload;
import lombok.Data;
import java.util.Set;
#Data
public class PostDTO {
private Long id;
private String title;
private String description;
private String content;
private Set<CommentDTO> comments;
}
Here is PostDTO class.
#Override
public PostDTO getPost(Long id) {
Post temp_post = postRepository.findById(id).
orElseThrow(() -> new ResourceNotFoundException("Post", "Id", id));
return mapToDTO(temp_post);
}
private PostDTO mapToDTO(Post post) {
return modelMapper.map(post, PostDTO.class);
}
I used mapToDTO method to convert post to postDTO.
But When I test it, the error message appeared.
{"timestamp":"2022-04-30T14:03:03.369+00:00","status":500,"error":"Internal Server Error","trace":"org.modelmapper.MappingException: ModelMapper mapping errors:\n\n1) Error mapping com.springboot.blog.entity.Post to com.springboot.blog.payload.PostDTO\n\n1 error\n\tat org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:380)\n\tat org.modelmapper.internal.
========================================================================================
** But when I replace the #Data annotation in class Post with #Getter, #Setter. It works perfectly! **

BeanCreationException because of Hibernate mapping

I'm getting this a BeanCreationException and I think it's because of my hibernate mappings.
I've been trying to figure out what mapping is wrong but no luck so far!
Customer class :
#Entity
#Data
#Table(name = "customer")
public class Customer {
#Id
#Column(name = "registration_code")
private String registrationCode;
private String name;
private String email;
private String phoneNumber;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "customer", cascade = {CascadeType.MERGE, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
private List<Order> orders;
}
Order class:
#Data
#Entity
#Table(name = "order")
public class Order {
#ManyToOne
#JoinColumn(name = "customer_code")
private Customer customer;
#Id
#OneToMany
#JoinColumn(name = "order_line_id")
private List<OrderLine> orderLines;
#Column(name = "date",columnDefinition = "DATE")
private LocalDate dateOfSubmission;
}
OrderLine class:
#Data
#Entity
#Table(name = "order_line")
public class OrderLine {
#Id
#Column(name = "order_line_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#ManyToOne
#JoinColumn(name = "product_code")
private Product product;
private Integer quantity;
}
Product class:
#Data
#Entity
#Table(name = "product")
public class Product {
#Id
private String skuCode;
private String name;
private Long price;
}
It's a spring boot application and I'm using Spring Data JPA

JPA OneToOne find all stuck in loop

I've a Java REST API with JPA. Whenever I create an entity, I also want to create another entity with a forgein key. Or maybe someone can advise me otherwise, I would really appreciate it and learn from it =)
When i successfully create a company it will make a file entity in the database as well, so that works fine. but,
Whenever I execute a findAll method in the JPA repository it will give me a loop of the one company that i've created.
like this:
If you need any more information, please let me know!
Company.class
package nl.hulpvriend.dehulpvriend.company;
import javax.validation.constraints.NotNull;
import lombok.*;
import nl.hulpvriend.dehulpvriend.file.File;
import javax.persistence.*;
import javax.validation.constraints.Size;
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Setter
#Getter
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotNull
private String email;
#Column(unique = true)
#NotNull(message = "The company name cannot be empty")
#Size(max = 30, message = "Company name cannot be longer than 30 characters")
private String name;
#NotNull(message = "Company must contain a service type")
#Enumerated(EnumType.STRING)
private ServiceType serviceType;
private double stars;
private Integer pricePerHour;
private String description;
private String kvk;
#OneToOne(mappedBy="company", cascade = CascadeType.ALL)
private File file;
}
File.class
package nl.hulpvriend.dehulpvriend.file;
import lombok.*;
import nl.hulpvriend.dehulpvriend.company.Company;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
#AllArgsConstructor
#Getter
#Setter
#NoArgsConstructor
#Entity
#Data
public class File {
#Id
private Integer id;
private String fileId;
#OneToOne(fetch = FetchType.EAGER)
#MapsId
private Company company;
#NotNull(message = "Must contain a data")
#Lob
private byte[] data;
private String downloadUrl;
private String fileName;
private String fileType;
public File(String fileName, String fileType, byte[] data) {
this.fileName = fileName;
this.fileType = fileType;
this.data = data;
}
}
Add JsonIgnore to one of the references to break the loop:
For example in the File class:
#JsonIgnore
#OneToOne(fetch = FetchType.EAGER)
#MapsId
private Company company;

Mapping a bidirectional One-to-Many Hibernate Entity with JPA

I am trying to map a bidirectional One-to-Many relationship in Hibernate. In the build logs I receive the error "repeated column in mapping for entity."
What is generating the error?
The entity source code is below. One has a compound primary key. I am using Lombok to generate getters and setters.
The relationship: Award (One) --> AwardReceived (Many)
Award Entity
#Entity
#Table(name = "awards")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class Award implements Serializable {
#Id
#Column(name = "award_id")
private Long awardId;
#OneToMany(cascade=CascadeType.ALL, mappedBy = "award")
private Set<AwardReceived> awardsReceived;
#Column(name = "award_type")
private String awardType;
#Column(name = "award")
private String award;
#Column(name = "description")
private String description;
}
AwardReceived Entity
#Entity
#Table(name = "awards_received")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceived implements Serializable{
#EmbeddedId
#JsonUnwrapped
private AwardReceivedPk awardReceivedPk;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;
#Column(name = "award_name")
private String awardName;
#Column(name = "citation")
private String citation;
}
AwardReceivedPk
#Embeddable
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceivedPk implements Serializable{
#JsonIgnore
#Column(name = "client_no")
private String clientNo;
#Column(name = "award_id")
private Long awardId;
#Column(name = "year")
private Long year;
}
Please try
#ManyToOne(cascade=CascadeType.ALL)
private Award award;
instead of
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;

StackOverflow Exception while using Hibernate and Jackson on bi-directional objects

I am trying some hibernate.The following is the pojo I am using,
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
#Column(name = "person_id")
private long person_id;
#Column(name = "name")
private String name;
#Column(name = "Address")
private String Address;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person" )
private Set<Phone> phone;
//Getters ande Setters
}
#Entity
#Table(name = "phone")
public class Phone{
#Id
#GeneratedValue
#Column(name = "phone_id")
private long phone_id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.MERGE,fetch = FetchType.EAGER)
#JoinColumn(name = "person_id")
private Person person ;
//Getters ande Setters
}
What I want is when I fetch a record from person and need corresponding all phone details. (Like Select * from person) I have around 1360 data in person and nearly double in phone. But for some reason error is thrown. I am not able to see full error stack . Below is the error I am getting.
at
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:117)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23)
~[jackson-databind-2.4.6.jar:2.4.6] at
.....
I was not able to post all error that I got
Using JsonManagedReference and JsonBackReference annotations may solve your problem.
While jackson trying to convert objects to json, visits objects and
their attributes. So if objects have bi-directional relations, for
jackson we need to think about cyclic dependencies. Jackson starts
serialize person and see the phone list and take a phone from list and
start serialize phone and sees person in phone and take person from
phone and start serilize it bla bla bla so this is an endless loop. If
jackson sees these annotations, stops and breaks the loop.
Give it a try as below code;
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
#Column(name = "person_id")
private long person_id;
#Column(name = "name")
private String name;
#Column(name = "Address")
private String Address;
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person" )
private Set<Phone> phone;
// Getters and Setters
}
#Entity
#Table(name = "phone")
public class Phone{
#Id
#GeneratedValue
#Column(name = "phone_id")
private long phone_id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.MERGE,fetch = FetchType.EAGER)
#JoinColumn(name = "person_id")
#JsonBackReference
private Person person;
// Getters and Setters
}
You can alternatively use #JsonIdentityInfo on classes
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Table(name = "phone")
public class Phone {
}
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Table(name = "person")
public class Person {
}
I was also getting the same error.
Using #JsonBackReference and #JsonManagedReference was still giving me error so I used #JsonIdentityInfo and it worked like a charm.
Below are my classes :-
BookModel :
#Data
#Entity
#Table(name = "book")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="bookId")
public class BookModel implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "book_id")
private int bookId;
#Column(name="book_name")
private String bookName;
#Column(name="book_author")
private String bookAuthor;
#Column(name="book_publish_date")
private Date bookPublishDate;
#Column(name="book_price")
private double bookPrice;
#OneToMany(mappedBy = "book_model")
List<BookImagesModel> bookImagesModels;
//getters and setters
//default constructor
}
BookImagesModel :
#Data
#Entity
#Table(name = "book_images")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="imageId")
public class BookImagesModel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "image_id")
private long imageId;
#ManyToOne
#JoinColumn(name = "book_id")
private BookModel book_model;
#Column(name = "image_path")
private String imagePath;
//getters and setters
//default constructor
}
I used Mysql8 database with spring boot.

Categories