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?
Related
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;
}
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;
I have a simple Order entity that contains OneToMany relation with a list of Dishes.
Order entity:
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#Table(name = "orders")
#ToString
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Enumerated(EnumType.STRING)
private Status status;
private LocalDateTime creationDate;
private LocalDateTime updateDate;
private BigDecimal totalPrice;
private String address;
#ManyToOne(fetch = FetchType.LAZY)
#ToString.Exclude
private User user;
#OnDelete(action = OnDeleteAction.CASCADE)
#OneToMany(
mappedBy = "order",
cascade = CascadeType.ALL,
orphanRemoval = true)
#ToString.Exclude
private List<Dish> dishes;
public Order(long id, Status status, BigDecimal totalPrice, String address, List<Dish> dishes) {
this.id = id;
this.status = status;
this.creationDate = LocalDateTime.now();
this.updateDate = LocalDateTime.now();
this.totalPrice = totalPrice;
this.address = address;
this.dishes = dishes;
}
}
Dish entity:
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#ToString
public class Dish {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String description;
private Category category;
BigDecimal price;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#ToString.Exclude
private Order order;
public Dish(long id, String name, String description, Category category, BigDecimal price) {
this.id = id;
this.name = name;
this.description = description;
this.category = category;
this.price = price;
}
public void setOrder(Order order) {
this.order = order;
order.addDish(this);
}
}
Here I try to save Orders containg these dishes
Dish dish1 = new Dish(0, "Dish first", "Description of first Dish", Category.SNACKS, BigDecimal.valueOf(100));
Dish dish2 = new Dish(0, "Dish second", "Description of second Dish", Category.BURGERS, BigDecimal.valueOf(100));
List<Dish> dishes1 = Arrays.asList(dish1, dish2);
List<Dish> dishes2 = Arrays.asList(dish2);
Order order1 = new Order(0, Status.PENDING, BigDecimal.valueOf(150), "Address 1", dishes1);
Order order2 = new Order(0, Status.COMPLETED, BigDecimal.valueOf(150), "Address 2", dishes2);
Here is the problem, Dishes are persisted together with orders, but not associated with the Order Entity.
Id is null
I know I didn't set order field when I created dishes, but how to do this If I need save both Order and Dishes at the same time.
You have the wrong model, what id do you expect to be in dish2?
Relation between Order and Dish is NOT one-to-many, but many-to-many. Hibernate does not know what to enter in the column.
I had entity for JSON parsing
#Entity
public class Product{
private int productId;
private String productName;
private BigDecimal productPrice;
private int productVendorId;
private String productVendorName;
private int productCategoryId;
private String productCategoryName;
//getters setters here
created 3 tables in dataBase:
products (product_id, product_name,product_price, product_vendor_id), product_category_id);
vendors(vendor_id, vendor_name); categories (category_id, category_name);
in 1st table product_vendor_id fk -> vendor_id pk in vendors and product_category_id fk -> category_id pk in categories
i tried something like this:
#Entity
#Table(name = "products, schema = "market")
public class Product
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int Id;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Column(name = "product_vendor_id")
private int productVendorId;
#Columnt(table = "vendors", name = "vendor_name")
private String vendor_name;
#Column(name = "product_category_id")
private int productCategoryId;
#Column(table = "categories", name = "category_name")
private String productCategorName;
//getters setters here
received alot of errors: like i have not category_name column in products table etc. this error i received when used
#Table(name = "products", schema = "market" )
#SecondaryTables({#SecondaryTable(name = "vendors", schema = "market"),
#SecondaryTable(name = "categories", schema = "market")})
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
....
#JoinColumn(name = "product_vendor_id", referencedColumnName = "vendor_id")
private int productVendorID;
#JoinColumn(table = "vendors", name = "vendor_name")
private String productVendorName;
#JoinColumn(name = "product_category_id", referencedColumnName =
"product_category_id")
private int productCategoryID;
#JoinColumn(table = "categories", name = "category_name")
private String productCategoryName;
exception:
Caused by: org.postgresql.util.PSQLException: ERROR: column
product0_1_.product_id doesn't exist
Hint: There may have been a link to the "product0_.product_id" column
Position: 705
how can i map this entity on 3 tables?
upd: i don't want separate this entity, i need this for deserialize my json object too, just want reuse this entity on different operations.
example of json
{"productID":"1111111","productName":"Cool product","productPrice":"99.99","productVendorName":"Some store","productVendorID":"1337","productCategoryName":"Food","productCategoryID":"1"}
Since there are 3 separate tables, you would want to create three separate entity classes.
Also I'm assuming vendors and category tables will have one to many relation to product.
Try below code:
Product:
#Entity
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#ManyToOne
#JoinColumn(name = "productCategoryId")
private Category category;
#ManyToOne
#JoinColumn(name = "productVendorId")
private Vendors vendor;
}
Category:
#Entity
public class Category {
#Id
private Integer categoryId;
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Vendors:
#Entity
public class Vendors {
#Id
private int vendorId;
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#NotEmpty
private List<Product> products = new ArrayList<>();
}
Though, I would recommend using above approach, if you still want to have single entity class and 3 separate table with redudant data then use below:
#Entity
#SecondaryTables({ #SecondaryTable(name = "vendors"), #SecondaryTable(name = "categories") })
public class Product {
#Id
private int productId;
private String productName;
private BigDecimal productPrice;
private String productVendorName;
private String productCategoryName;
#Column(table = "categories")
private Integer categoryId;
#Column(table = "categories")
private String categoryName;
#Column(table = "vendors")
private int vendorId;
#Column(table = "vendors")
private String vendorName;
}
The id column of the main table will be present in all the 3 tables and used for joining them.
Sorry for poor wording of the question, just didn't know how to explane what i wanted.
All what i need just add #transient annotations for fields which i don't have in products table, and separate it like accepted answer was suggested.
#Entity
#Table(name = "products", schema = "store" )
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product {
#Id
#Column(updatable = false, nullable = false, name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_price")
private BigDecimal productPrice;
#Transient
private String productVendorName;
#Transient
private String productCategoryName;
#Transient
private int vendorId;
#Transient
private int categoryId;
#ManyToOne
#JoinColumn(name = "product_category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "product_vendor_id")
private Vendor vendor;
}
for vendors table entity
#Entity
#Table(name = "vendors", schema = "store")
public class Vendor {
#Id
#Column(name = "vendor_id")
private int vendorId;
#Column(name = "vendor_name")
private String vendorName;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
and for categories
#Entity
#Table(name = "categories", schema = "store")
public class Category {
#Id
#Column(name = "category_id")
private Integer categoryId;
#Column(name = "category_name")
private String categoryName;
#OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
#NotNull
private List<Product> products = new ArrayList<>();
}
Wanted to leave here full answer on my question, maybe someone will need it later
Just check some problems with toString. Use it only in Product.class and better make 2 versions for print json and jpa.
Student.java
#Entity
#Table(name = "Student")
#Data
#NoArgsConstructor
public class Student implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "studentId", cascade = CascadeType.ALL)
private List<Subject> subjectList = new ArrayList<>();
public void addSubject(Subject subject) {
subjectList.add(subject);
subject.setStudentId(this);
}
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
}
Subject.java
#Entity
#Table(name = "Subject")
#Data
#NoArgsConstructor
public class Subject implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="studentId", nullable = false)
private Student studentId;
#Column(name = "subjectName")
private String subjectName;
#Column(name = "subjectCode")
private int subjectCode;
}
SubjectRepository.java
#Repository
public interface SubjectRepository extends JpaRepository<Subject, Long> {
}
As shown in the code structure above, I have 2 entities (Student, Subject) and a repository class (SubjectRepository). When i try to save into the Subject table, somehow the student name "Thomas" from the Student table gets updated as well in the database. I would like to only insert into Subject table without having any values from the Student table getting updated. Need some help on this. Thanks!
public static void main(String[] args) {
#Autowired protected SubjectRepository subjectRepository;
Student student = new Student();
student.setFirstName("Thomas");
Subject subject = new Subject();
subject.setSubjectName("Chemistry");
subject.setSubjectCode(12345);
student.addSubject(subject)
subjectRepository.save(subject)
}
I would like to only insert into Subject table without having any values from the Student table getting updated
You can achieve this with following code :
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="studentId", nullable = false, updatable = false)
private Student studentId;
When using Spring JPA I would suggest using the JpaRepository API. You just need to pass in your entity, and it should save as desired.
Ex:
subjectRepository.save(subject);
You have try this
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name="studentId", nullable = false, updatable = false)
private Student studentId;
#MaxExplode You have to use cascade = CascadeType.REFRESH then other details will not update. but if you are try to set updateStudent.setfirstNamr(student.getFirstName()); and then save parent object then i will update. otherwise it will not update.