foreign key is null Springboot jpa - java

customer
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "customer_id")
private Long customerId;
#NonNull
#Column(name = "name")
private String name;
#NonNull
#Column(name = "address")
private String address;
#NonNull
#Column(name = "house_no")
private String houseNo;
#Column(name = "active")
private boolean active = true;
#NonNull
#Column(name = "customer_type")
private String customerType;
#NonNull
#Column(name = "pack")
private String pack;
#JsonIgnore
#OneToOne(mappedBy = "customer",cascade = CascadeType.ALL)
private Stb stb;
#JsonIgnore
#OneToOne(mappedBy = "customer",cascade = CascadeType.ALL )
private Payment payment;
#JsonIgnore
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private List<History> history;
}
History
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "history")
public class History {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "history_id")
private Long historyId;
#Column(name = "amount_paid")
private Long AmountPaid;
#LastModifiedDate
#Column(name = "payment_date")
private String paymentDate;
#Column(name = "due")
private Long due;
#JsonIgnore
#ManyToOne(optional = false,fetch=FetchType.LAZY)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
payment
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "payment")
public class Payment {
public Long normalPrice =220L;
public Long sportsPrice = 250L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "payment_id")
private Long paymentId;
#Nonnull
#Column(name = "amount_paid")
private Long paid;
#Nullable
#LastModifiedDate
#Column(name = "payment_date")
private String paymentDate;
#Nullable
#Column(name = "due")
private Long due;
#JsonIgnore
#OneToOne(fetch=FetchType.EAGER,optional=false)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
stb
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "stbox")
public class Stb {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "stb_id")
private Long StbId;
#NonNull
#Column(name = "stbox_number")
private String StboxNumber;
#NonNull
#Column(name = "stbox_id")
private String StboxId;
#NonNull
#Column(name = "stbox_cust_number")
private String StboxCustNumber;
#NonNull
#Column(name = "stbox_type")
private String StboxType;
#JsonIgnore
#OneToOne(optional = false,fetch=FetchType.LAZY)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
im new to springboot , i just assigned foreign key in many ways i watched many tutorials and blogs and tried it out but it all failed , the foreign key is always set to null, anybody help , thanks in advance :) .
im trying to create a foreign key in stb , payment ,history but i refered it correctly but it ssets to null

Are you setting both sides of the joins?
public class Customer {
public void setStb(Stb stb) {
this.stb = stb;
stb.customer = this;
}
}
or outside maybe?
public void setCustomerStb(Customer customer, Stb stb) {
customer.setStb(stb);
stb.setCustomer(customer);
}
The same also applies to the other joins.

Related

Spring Boot API: Failing to save object to Database using Spring Boot

I have already built projects similar to this one, I even based this one in a different project I have. Thing is, I don't see why it keeps failing when I try to save an object to the Database. These are my Classes:
Car
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity(name = "cars")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
#NotBlank
private String brand;
#Column
#NotBlank
private String model;
#Column
#NotBlank
private String color;
#Column
#NotBlank
private int kilometers;
#Column(name = "fabrication_date")
private LocalDate fabricationDate;
#Column
#PositiveOrZero
private float price;
#Override
public String toString() {
return "------------------------------------------------------------"+ "\n"
+brand + " - " + model;
}
#OneToMany(mappedBy = "car")
#JsonBackReference(value = "car-purchases")
private List<Purchase> purchases;
}
Purchase
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "purchases",
uniqueConstraints = { #UniqueConstraint(columnNames =
{ "user_id", "car_id" }) })
public class Purchase {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "creation_date")
private LocalDate creationDate;
#Column
private float price;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#ManyToOne
#JoinColumn(name = "car_id")
private Car car;
}
This is the Add to Database function:
#Override
public CarOutDTO addCar(CarInDTO carInDTO) {
Car car = new Car();
modelMapper.map(carInDTO, car);
car.setFabricationDate(LocalDate.now());
car.setKilometers(0);
Car newCar = carRepository.save(car); <--- It fails here
CarOutDTO carOutDTO = new CarOutDTO();
modelMapper.map(car, carOutDTO);
return carOutDTO;
}
And, this is the info that comes when I try sending a POST:
I can't find the error here, I assume it has something to do with this part, maybe the #JsonBackReference part?
#OneToMany(mappedBy = "car")
#JsonBackReference(value = "car-purchases")
private List<Purchase> purchases;

how to save bidrectional entity with dto

I have two spring boot entities MeetingSetting and MeetingTime, MeetingSetting can have multiple MeetingTimes. I am trying to save these to at the same time with the DTO structure, so I can avoid the circular reference problem when I am getting MeetingTimes. Saving partially works. MeetingSettings has a property called meetingName which is a foreign key in meetingTimes. Everything except meetingName is saved which is for some reason null, but I can not find the reason, could someone maybe look at my code and tell me what I am missing?
MeetingSetting Entity:
#Entity
#Table(name = "meeting_settings")
#Setter
#Getter
public class MeetingsSetting implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name", unique = true)
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meetingName", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingSettingDTO:
#Getter
#Setter
public class MeetingSettingDTO {
private Long id;
#NotNull
private String meetingName;
#NotNull
private String meetingUrl;
#NotNull
private String meetingPw;
private Set<MeetingTime> meetingTime;
}
MeetingTime Entity:
#Entity
#Table(name = "meeting_times")
#Getter
#Setter
public class MeetingTime implements Serializable {
#JsonIgnore
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "meeting_name" , referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
}
MeetingTimeDTO:
#Getter
#Setter
public class MeetingTimeDTO {
private Long id;
#NotNull
private String date;
#NotNull
private String startTime;
#NotNull
private String endTime;
private Set<MeetingSettingDTO> meetingSettings;
}
And finally the controller where I am saving everything (Just save method):
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingSettingDTO meetingSettingDTO){
MeetingsSetting meetingsSetting = new MeetingsSetting();
meetingsSetting.setMeetingName(meetingSettingDTO.getMeetingName());
meetingsSetting.setMeetingPw(meetingSettingDTO.getMeetingPw());
meetingsSetting.setMeetingUrl(meetingSettingDTO.getMeetingUrl());
Set<MeetingTime> meetingTimeSet = meetingSettingDTO.getMeetingTime();
meetingsSetting.setMeetingTime(meetingTimeSet);
meetingSettingService.saveMeeting(meetingsSetting);
}
My service is just implementing a jpaRepository which takes MeetingSetting as parameter
In your MeetingTime entity class you have a parent:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "meeting_name" , referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
You have to set it explicitly for each MeetingTime, so add this:
Set<MeetingTime> meetingTimeSet = meetingSettingDTO.getMeetingTime();
meetingTimeSet.forEach(m -> m.meetingName(meetingsSetting));

how to save entities in a relation to database in spring boot

I have a spring boot application with two entities in a relationship. MeetingSetting and MeetingTime meetingSetting can have unlimited meetingTimes. So far the databases are generating without problem, but When I try to save my Entity they are saved but different from each other, they are saved independently. Meaning MeetingName which is a foreign key inside MeetingTime is not saved but seen as null (I debugged and tried finding out why but could not find anything) THe other values are saved-
could someone point me out what my error is?
this is the json I am sending:
{
"meetingName":"TEst",
"meetingPw":"",
"meetingTime":[
{
"date":"2021-05-31",
"startTime":"15:30",
"endTime":"16:30"
},
{
"date":"2021-06-21",
"startTime":"15:30",
"endTime":"17:30"
},
{
"date":"2021-06-21",
"startTime":"11:01",
"endTime":"11:01"
}
]
}
MeetingSettings:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name", unique = true)
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meeting_Name", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingTime:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false , referencedColumnName = "meeting_name")
private MeetingsSetting meeting_Name;
}
this is how I try to save the entity:
#RestController
#RequestMapping("/api/meetingSetting")
public class MeetingSettingController {
#Autowired
MeetingSettingService meetingSettingService;
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingSettingService.saveMeeting(meetingsSetting);
}
}
My service calls the save method of an jpaRepository.
In a bi-directional One to Many, you have to synchronize both sides of the association.
You can simply iterate over all MeetingTime objects and set the corresponding MeetingSetting to it.
Your MeetingSettingService's saveMeeting method could do this:
public void saveMeeting(MeetingsSetting meetingsSetting) {
// ...
// here you're synchronizing both sides of the association
meetingsSetting.getMeetingTime()
.forEach(mt -> mt.setMeetingSetting(meetingSetting));
// ...
repository.save(meetingSetting);
}
Solution to my question, I am not sure if this is a good or correct way of solving this maybe someone can advice me a better solution:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "meeting_name")
private String meeting_name;
THIS IS THE PART WHICH IS CALLED FROM THE METHOD INSIDE MEETINGSCONTROLLER
#Column(name = "end_time")
private String endTime;
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false, referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
}
MeetingsTime Entity:
#RestController
#RequestMapping("/api/meetingSetting")
public class MeetingSettingController {
#Autowired
MeetingSettingService meetingSettingService;
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingsSetting.getMeetingTime()
.forEach(mt -> mt.setMeeting_name(meetingsSetting.getMeetingName()));
// ...
meetingSettingService.saveMeeting(meetingsSetting);
}
}

how to save entity with relationship in spring boot

I have a spring boot application where I want to send an json object with a relationship. I have one entity called meetingSetting and one called meetingTime. MeetingSetting can have as many meetingTimes as possible and one meetingTime object belongs to one meetingSetting. But when I try to send it I am getting the following error:
not-null property references a null or transient value : com.cbc.coorporateblinddateservice.entities.dates.MeetingTime.meetingsSetting
I tried debugging and noticed that meetingSetting is empty when it is sent inside the times object send in the json. Could someone look at my code and tell me what I am missing, my guess is that I have to extend my saveMethod in meetingSettings but it is just a guess.
here is my MeetingSetting entity:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name")
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meetingsSetting", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
meetingTime entity:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne()
#JoinColumn(name = "meeting_settings_name", nullable = false)
private MeetingsSetting meetingsSetting;
}
MeetingSettingCOntroller:
#RestController
#RequestMapping("/api/meetingSetting")
public class MeetingSettingController {
#Autowired
MeetingSettingService meetingSettingService;
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingSettingService.saveMeeting(meetingsSetting);
}
Service:
#Service
public class MeetingSettingService {
#Autowired
MeetingSettingRepository meetingSettingRepository;
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingSettingRepository.save(meetingsSetting);
}
Update new code:
MeetingTime:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "meeting_name", nullable = false)
private MeetingsSetting meetingName;
}
MeetingSettings:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name")
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meetingName", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
Sql script:
create table meeting_times
(
id bigint auto_increment
primary key,
meeting_date varchar(255) null,
start_time varchar(255) null,
end_time varchar(255) null,
meeting_name varchar(255) null,
constraint fk_meeting_times__meeting_settings_name
foreign key (meeting_name) references meeting_settings (meeting_name)
);
The reason you're getting a null issue is that on #JoinColumn(name = "meeting_settings_name", nullable = false) you've got nullable = false. the column you're joining on is meeting_settings_name which doesn't seem to be a column on meeting_times and the actual name on meeting_settings is meeting_name. You'll have to add meeting_name to meeting_times to create a relation between the two tables to get this to work.

How can i apply native join query in spring data jpa?

Here are my entity classes.
JobPost.java
#Entity
#Table(name = "job_post")
public class JobPost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "job_post_id")
private Long jobPostId;
#Column(name = "job_title")
private String jobTitle;
#Column(name = "job_description")
private String jobDescription;
#Column(name = "vacancy")
private int vacancy;
#Column(name = "posted_date")
#JsonFormat(pattern = "yyyy-MM-dd")
private Date postedDate;
#Column(name = "total_applicants")
private int totalApplicants;
}
JobApplication.java
#Entity
#Table(name = "job_application")
public class JobApplication {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "job_application_id")
private Long jobApplicationId;
#Column(name = "job_post_id")
private Long jobPostId;
#Column(name = "applicant_id")
private Long applicantId;
}
Applicant.java
#Entity
#Table(name = "applicant")
public class Applicant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "applicant_id")
private Long applicantId;
#Column(name = "applicant_name")
private String applicantName;
#Column(name = "applicant_mobile_no")
private String applicantMobileNo;
#Column(name = "applicant_email")
private String applicantEmail;
}
My main goal is to listing the ApplicantList on JobPostId. I am totally new in Spring data JPA. Is JPA mappings are correct?. I don't know which query I should fire in order to fetch the applicantList based on jobPostId.
I would recommend to use JpaMappings and use SpringData instead of using native query.
Steps to follow:
Many-To-Many:
Use JoinTable to directly map JobPost and Applicant instead of creating a separate class.
Link for help:
https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping
Use SpringData JPA findOne or findById method (depends on spring version). If you use EAGER fetch then it will give you all Applicants associated with the JobPost Id.
One-To-Many
Keep JobApplication class and use OneToMany annotation.
Link for help:
https://attacomsian.com/blog/spring-data-jpa-one-to-many-mapping
Query:
#Query("select a from JobPost j inner join j.jobApplicantList ja inner join ja.applicant a where j.jobPostId=:jobPostId")
List<String> findAllJobApplicants(#Param("jobPostId") Long jobPostId);
I think that you should configure the mappings in such a way.To do this, you only need two entities
JobPost.java
#Entity
#Table(name = "job_post")
public class JobPost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "job_title")
private String jobTitle;
#Column(name = "job_description")
private String jobDescription;
#Column(name = "vacancy")
private int vacancy;
#Column(name = "posted_date")
#JsonFormat(pattern = "yyyy-MM-dd")
private Date postedDate;
#Column(name = "total_applicants")
private int totalApplicants;
#ManyToMany
#JoinTable(name = "applicant_job_post",
joinColumns = {
#JoinColumn(name = "job_post_id", referencedColumnName = "id")
}, inverseJoinColumns = {
#JoinColumn(name = "applicant_id", referencedColumnName = "id")
})
private Set<Applicant> applicants;
public JobPost() {
}
public void addApplicant(Applicant applicant) {
applicants.add(applicant);
applicant.getJobPosts().add(this);
}
public void removeApplicant(Applicant applicant) {
applicants.remove(applicant);
applicant.getJobPosts().remove(this);
}
}
Applicant.java
#Entity
#Table(name = "applicant")
public class Applicant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "applicant_name")
private String applicantName;
#Column(name = "applicant_mobile_no")
private String applicantMobileNo;
#Column(name = "applicant_email")
private String applicantEmail;
#ManyToMany(mappedBy = "applicants")
private Set<JobPost> jobPosts;
public Applicant() {
}
public void addJobPost(JobPost jobPost) {
jobPosts.add(jobPost);
jobPost.getApplicants().add(this);
}
public void removeJobPost(JobPost jobPost) {
jobPosts.remove(jobPost);
jobPost.getApplicants().remove(this);
}
}

Categories

Resources