Recently I got an issue I can't seem to figure out. I have entity class called order that has a one to one relationship with two other entity classes called Product and Customer. When I try to set the customer the foreign key is set in the database. However when I try to do the same thing with the product he doesn't do it. The customer is created in the database the moment when the order is made. But the product is retrieved from the database.
My apologies for the written code. This is the controller we use to save the entities to the mysql database
#RequestMapping(value = "/makeorder", method = RequestMethod.POST)
public String MakeOrder(#RequestBody String Json, RedirectAttributes ra) throws IOException {
List<Orders> o = new ArrayList<>();
String[] lijst = Json.split("r");
String[] naamsplit = Json.split("CustomerNaam" + "=");
String naam = naamsplit[1].substring(0, naamsplit[1].indexOf("&"));
naam = naam.replace("+", " ");
String[] adressplit = Json.split("CustomerAdres" + "=");
Customer customersaved = new Customer();
String adres = adressplit[1].substring(0, adressplit[1].indexOf("&"));
adres = adres.replace("+", " ");
if (naam != "" && adres != "") {
if (Json.contains("=on")) {
for (int i = 0; i < lijst.length; i++) {
if (lijst[i].contains("=on")) {
String[] getidstring=lijst[i].split("boolean");
int getidnum=parseInt(getidstring[1].substring(0,getidstring[1].indexOf("=")));
Optional<Product> optionalEntity = productRepository.findById(Long.valueOf(getidnum));
Product product = optionalEntity.get();
Orders order = new Orders();
String splitter=getidnum+"=";
String[] lijst2 = lijst[i].split(splitter);
int nummer = parseInt(lijst2[1].substring(0, 1));
order.setNumberOfProducts(nummer);
order.setCustomer(customersaved);
orderRepository.save(order);
var updateOrder = orderRepository.findById(order.getId());
Orders orderUpdated = updateOrder.get();
orderUpdated.setProduct(product);
orderRepository.save(orderUpdated);
}
}
return adres;
}
else
{
return "redirect:/";
}
}
else
{
return "redirect:/";
}
}
These are the entities Product, Customer and Order
Product:
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "products")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "productid")
private Long id;
#Column(name = "productname")
private String name;
#Column(name = "price")
private Double price;
#Column(name = "availability")
private boolean availability;
#Column(name = "photo")
private byte[] photo;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "product_category",
joinColumns = #JoinColumn(name = "productid"),
inverseJoinColumns = #JoinColumn(name = "categoryid"))
#JsonManagedReference
#JsonIgnore
private List<Category> category;
#OneToOne(mappedBy = "Product")
private Orders Order;
}
Customer:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "customers")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "customerid")
private Long id;
#Column(name = "firstname")
private String firstname ;
#Column(name = "lastname")
private String lastname ;
private String address;
#OneToMany(mappedBy = "customer")
private List<Orders> orders;
}
Order:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "Orders")
public class Orders {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "orderid")
private Long id;
#Column(name = "numberofproducts")
private int numberOfProducts;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="customerid")
private Customer customer;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn
private Timeslot timeslot;
#OneToOne
#PrimaryKeyJoinColumn
private Product Product;
}
Related
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.
I am unable to solve this error. java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'ordered_songs.UK_q73sm6y7ob1asdtqty7nxbj2j'
I have a many to many relationship annotation with Order and Song, which points to collection type elements. I can successfully add one order, but after that my app breaks when trying to add a second order, and I cannot seem to figure out why. It looks as though order id is not being incremented when it's called in the controller.
Here is my Order POJO
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "ord")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToMany
#JoinTable(name = "ordered_songs", joinColumns = #JoinColumn(name = "song_id"), inverseJoinColumns = #JoinColumn(name = "order_id"))
#ElementCollection
private List<Song> orderedSongs = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "customer_id")
private Customer customer;
private String status;
private Date date;
#Embedded
private MailingAddress mailingAddress;
}
The second POJO is
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Embeddable
public class Song {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String title;
private String description;
private String artist;
private String genre;
private String format;
private double price;
private String imageUrl;
#ManyToMany(mappedBy = "orderedSongs")
#ElementCollection
#ToString.Exclude
private List<Order> orders = new ArrayList<>();
// private Order order;
}
Here is my controller
#PostMapping("/mailing")
public ModelAndView saveMailingAddress(#RequestParam("street") String street,
#RequestParam("city") String city,
#RequestParam("state") String state,
#RequestParam("zip") int zip,
ModelMap model) {
Customer c=(Customer) model.get("customer");
MailingAddress ma=new MailingAddress();
ma.setStreet(street);
ma.setCity(city);
ma.setState(state);
ma.setZip(zip);
Order o=new Order();
o.setStatus("ordered");
o.setDate(new Date());
c.getOrders().add(o);
o.setCustomer(c);
o.setMailingAddress(ma);
Order o1 = orderDao.save(o);
System.out.println("first msg b4 for loop");
for(Song s: cs.getSongs()) {
System.out.println("b4 add to o1");
o1.getOrderedSongs().add(s);
System.out.println("b4 save");
songDao.save(s);
System.out.println("after save");
}
System.out.println("after loop");
cs.removeAll();
return new ModelAndView("success");
}
What am I doing wrong here?
When inserting a record using post request foreign key related reference record is not linking.
#RestController
#RequestMapping("auth")
public class PatientController {
#Autowired
private PatientService patientService;
#PostMapping(value = "patient/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public String registerPatient(#RequestBody Patient patient) {
String response = patientService.registerPatient(patient);
return "{'result':" + response + "}";
}
}
#Service
public class PatientService {
#Autowired
private PatientRepository patientRepo;
public String registerPatient(Patient patient) {
patient = patientRepo.save(patient);
}
}
#Repository
public interface PatientRepository extends CrudRepository<Patient, Integer> {
}
Entity Classes:
#Entity
#Table(name = "patient")
public class Patient implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "patient_id")
private int patientId;
#Column(name = "patient_name", length = 200)
private String patientName;
#Column(name = "problem", length = 200)
private String problem;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
private Doctor doctor;
}
#Entity
#Table(name = "doctor")
public class Doctor implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "doctor_id")
private int doctorId;
#Column(name = "doctor_name", length = 200)
private String doctorName;
#Column(name = "department", length = 200)
private String department;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
Database - Doctor Table:
doctor_id doctor_name department
12345678 Dfirstname Dlastname ENT
POST Request - JSON Body
{
"patientName":"Pfirstname Plastname",
"problem:"visibility problem - difficulty in low light",
"doctor":{"doctorId":"12345678"}
}
When I am sending this request the patient table doctor_id column is not being populated with the docortId.
at first glance (as service layer is not provided) You have to remove insertable=false and updatable=false from #JoinColumn
#JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
change this to:
#JoinColumn(name = "doctor_id", nullable = false)
As this directives doesn't let jpa to insert/update the DOCTOR_ID column
Also I prefer using werappers over primitive type as #Id change int to Integer as suggested here Using wrapper Integer class or int primitive in hibernate mapping
Also it seems that you have already persisted doctor (as it has already assigned id) you should firstly select doctor to db and add patient to it with both ends:
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
here is full example:
public static void main(String[] args) {
SpringApplication.run(DemostackApplication.class, args);
}
#Component
public static class AppRunner implements ApplicationRunner {
#Autowired
MainService mainService;
#Override
public void run(ApplicationArguments args) throws Exception {
Doctor doctor = new Doctor();
doctor.department = "a";
doctor.doctorName = "Covid19 Ninja";
doctor = mainService.saveDoctor(doctor);
Patient patient = new Patient();
patient.patientName = "test";
patient.problem = "test";
patient.assignToDoctor(doctor);
Patient newPatient = mainService.savePatient(patient);
}
}
#Service
public static class MainService {
#Autowired
DoctorRepo doctorRepo;
#Autowired
PatientRepo patientRepo;
#Transactional
public Doctor saveDoctor(Doctor doctor) {
return doctorRepo.save(doctor);
}
#Transactional
public Patient savePatient(Patient patient) {
return patientRepo.save(patient);
}
}
#Entity
#Table(name = "patient")
public static class Patient implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "patient_id")
private Integer patientId;
#Column(name = "patient_name", length = 200)
private String patientName;
#Column(name = "problem", length = 200)
private String problem;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "doctor_id", nullable = false)
private Doctor doctor;
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
}
#Entity
#Table(name = "doctor")
public static class Doctor implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "doctor_id")
private Integer doctorId;
#Column(name = "doctor_name", length = 200)
private String doctorName;
#Column(name = "department", length = 200)
private String department;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
I have not used getter/setters but you should :)
EDIT
your registerPatient() logic should be something like this:
#Transactional
public String registerPatient(Patient patient) {
Integer doctorId= patinet.getDoctor().getId();
//fetch the doctor from database
Doctor doctor = doctorRepository.findById(doctorId).orElseThrow(() -> new RuntimeException("doctor not found"));
//create bidirectional reference between patient and doctor
patient.setDoctor(doctor);
doctor.getPatients().add(patient);
//save patient
patient = patientRepo.save(patient);
return "OK";
}
I have a Production class and ProductionDetail entity class where Id of Production table is a foreignKey as production_id in ProductionDetail entity class so my both entity class with mapping has given bellow
Production Entity Class:
#Entity
#Table(name = "tbl_production")
#XmlRootElement
public class TblProduction implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "ID")
private String id;
#Column(name = "PRODUCTION_DATE")
#Temporal(TemporalType.DATE)
private Date productionDate;
#Column(name = "START_DATETIME")
#Temporal(TemporalType.TIMESTAMP)
private Date startDatetime;
#Column(name = "END_DATETIME")
#Temporal(TemporalType.TIMESTAMP)
private Date endDatetime;
#Size(max = 45)
#Column(name = "MACHINE_UUID")
private String machineUuid;
**Relation with Production Details Table**
#OneToMany(mappedBy = "production")
#XmlElement(name = "productionDetails")
private List<TblProductionDetail> productionDetailList;
#PrimaryKeyJoinColumn(name = "MACHINE_UUID", referencedColumnName = "UUID")
#ManyToOne(fetch = FetchType.LAZY)
private MstMachine mstMachine;
#XmlTransient
public MstMachine getMstMachine() {
return this.mstMachine;
}
}
Production Details Entity Class:
#Entity
#Table(name = "tbl_production_detail")
#XmlRootElement
public class TblProductionDetail implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "ID")
private String id;
#Size(max = 45)
#Column(name = "COMPONENT_ID")
private String componentId;
#Size(max = 45)
#Column(name = "PRODUCTION_ID")
private String productionId;
**Relation with Production Class**
#ManyToOne
#JoinColumn(name = "PRODUCTION_ID", referencedColumnName = "ID", insertable = false,
updatable = false)
private TblProduction production;
#Transient
public String componentCode;
#Transient
public String componentName;
#PrimaryKeyJoinColumn(name = "COMPONENT_ID", referencedColumnName = "ID")
#ManyToOne(fetch = FetchType.LAZY)
private MstComponent mstComponent;
#XmlTransient
public MstComponent getMstComponent() {
return this.mstComponent;
}
public void setMstComponent(MstComponent mstComponent) {
this.mstComponent = mstComponent;
}
}
ParentList Class:
public class TblProductionList {
private List<TblProduction> productionList;
public TblProductionList() {
productionList = new ArrayList<>();
}
public List<TblProduction> getTblProductions() {
return productionList;
}
public void setTblProductions(List<TblProduction> tblProductionList) {
this.productionList = tblProductionList;
}
}
BusinessLogic(DAO Class):
public TblProductionList getJson() {
TblProductionList response = new TblProductionList();
StringBuilder retrieveQuery = new StringBuilder();
retrieveQuery.append(" SELECT prod FROM TblProduction prod ");
retrieveQuery.append(" JOIN FETCH prod.productionDetailList ");
retrieveQuery.append(" WHERE prod.endDatetime IS NULL ");
retrieveQuery.append(" AND prod.machineUuid IS NOT NULL ");
retrieveQuery.append(" AND NOT EXISTS (SELECT tpt FROM
TblProductionThset tpt WHERE prod.id = tpt.productionId) ");
retrieveQuery.append(" AND EXISTS (SELECT mmfd FROM
MstMachineFileDef mmfd WHERE prod.machineUuid = mmfd.machineUuid
AND mmfd.hasThreshold = 1) ");
retrieveQuery.append(" ORDER BY prod.id ");
Query query =
entityManager.createQuery(retrieveQuery.toString());
List thresholdList = query.getResultList();
response.setTblProductions(thresholdList);
return response;
}
According to the database I am getting expected master child data like below
After designing this entity class I am expecting that I will get 3 master records where each record has 2 detail records. But I am getting 6 duplicate master records with 12 child records. Can anyone suggest to me please where is my code became wrong and why this situation raised? please check the JSON data that I am getting from API.
change your array list to hash set then records are not duplicate.
I have two entities Courses and CourseUser. Courses mapped with OneToMany annotation to a CourseUser. After i add a CourseUser in a list of CourseUsers in Course and update it, new row appears in table CourseUser but it doesn't mapped to a Courses. If i call toString of courseUsers list from courses after update it will be empty.
#Entity
#Table(name = "COURSES")
public class Courses{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "course_id")
private int course_id;
#Column(name = "course_name", nullable = false)
private String courseName;
#Autowired
#OneToMany(mappedBy = "course", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<CourseUser> courseUsers = new HashSet<>(0);
CourseUser entity:
#Entity
#Table(name = "COURSE_USERS",
uniqueConstraints = {#UniqueConstraint(columnNames = {"course_name", "user_name"})})
public class CourseUser {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ev_id")
private int ev_id;
#Column(name = "course_name", nullable = false)
private String courseName;
#Column(name = "user_name", nullable = false)
private String userName;
#Column(name = "course_role")
private String courseRole;
#Column(name = "grade")
private int grade ;
#ManyToOne
#JoinColumn(name = "course_id")
private Courses course;
this is how i add new courseUser to a course :
Courses course = courseDAO.getCourse(id);
Set<CourseUser> courseUsers = course.getCourseUsers();
CourseUser newUser = new CourseUser();
newUser.setUserName(name);
newUser.setCourseRole(role);
newUser.setCourseName(course.getCourseName());
courseUsers.add(newUser);
course.setCourseUsers(courseUsers);
update(course);
and here is CoursesDAO update method:
public void update(Courses course) {
Session session = sf.openSession();
Transaction transaction = session.beginTransaction();
session.merge(course);
session.flush();
transaction.commit();
session.close();
}
At first, you have to save entity, which is referenced by id.
In your case, you have to save CourseUser at first, and then add it to Course.
For example:
Courses course = courseDAO.getCourse(id);
Set<CourseUser> courseUsers = course.getCourseUsers();
CourseUser newUser = new CourseUser();
newUser.setUserName(name);
newUser.setCourseRole(role);
newUser.setCourseName(course.getCourseName());
// this row is very important
// after thus operation newUser will have an id to be referenced
courseUserDto.save(newUser);
courseUsers.add(newUser);
course.setCourseUsers(courseUsers);
update(course);
Also, there is some redundant code that you wrote:
Set<CourseUser> courseUsers = course.getCourseUsers();
// ...
course.setCourseUsers(courseUsers);
course already stores reference to courseUsers.