Hibernate Formula with join - spring

i have an entity order and an entity order_items ( 1->n relation).
I want a field in order that table that show the sum(quantity) of related order items. These are my entities:
#Entity(name="ORDERS")
public class Order {
#Id
#GeneratedValue
#Column (name="order_id")
private long id;
#OneToOne
#JoinColumn(name="customer_id")
private Customer customer;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "order", cascade =CascadeType.ALL)
#JsonManagedReference
private List<OrderItem> orderItems=new ArrayList();
#Entity(name="ORDER_ITEMS")
public class OrderItem {
#Id
#GeneratedValue
#Column (name="order_item_id")
private long id;
#Column (name="quantity")
private int quantity;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "order_id", nullable = false)
#JsonBackReference
private Order order;
I want a new field in Order entity that show the total quantity ( sum of quantity of the childs).
I've tried to add the field in order but it not works
#Formula("select sum(oi.quantity) from ORDER_ITEMS oi where oi.order_id= order_id)")
private int totalQuantity;
Can you help me to fix it ?

The solution
#Formula("(select sum(oi.quantity) from ORDER_ITEMS oi where oi.order_id= order_id)")
private int totalQuantity;

Related

JPA composite key spring boot

I made 2 one-to-one relationships with 2 foreign keys, but I can't make a constraint or how could I make the 2 unique keys be a unique key in the new table?
#Table(name = "cart")
public class Cart {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
private int quantity;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "product_id")
private Product products;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User users;
}
#Entity
#Table(name = "Products")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int quantity;
private Double price;
private String image;
It spells my 2 keys correctly, for example
user_id = 2 , product_id =2 would be ok
but if I enter another user_id=2, product_id=2 should not work, but for me it is entered in the database
You can use #PrimaryKeyJoinColumn in the #OneToOne relation:
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn(name = "product_id", referencedColumnName = "id")
private Product products;

In Hibernate how to ignore associated table in selection

I am using spring boot and Hibernate and I have two tables order and orderdetails and I need two queries, first I want to select records in order along with records that relate to that order in order detail table which works fine, but when I want to select only records from order table I can't because it will bring all associated records for each order in the order detail(just like the first one). How I can select records from the order without selecting related records in order detail table?
I also tried to use #JsonIgnore annotation but it doesn't work like what I want.
My entity classes
orders
#Entity
#Setter
#Getter
public class Orders {
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "order_id")
private Long orderId;
#Column(name = "user_id")
private Long userId;
#Column(name = "user_name")
private String userName;
#Column(name = "created_date", columnDefinition = "DATE")
#JsonFormat(pattern = "MM/dd/yyyy")
private LocalDate createdDate;
private String status;
private float amount;
#Transient
String error;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private List<OrderDetail> orderDetails;
}
order detail
#Entity
#Setter
#Getter
public class OrderDetail {
public OrderDetail() {
}
public OrderDetail(Long productId, String productName, int quantity, float unitPrice, float subtotalPrice){
this.productId = productId;
this.productName = productName;
this.quantity = quantity;
this.unitPrice = unitPrice;
this.subtotalPrice = subtotalPrice;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "order_detail_id", nullable = false)
Long orderDetailId;
#Column(name = "product_id")
Long productId;
#Column(name = "product_name")
String productName;
int quantity;
#Column(name = "unit_price")
float unitPrice;
#Column(name = "subtotal_price")
float subtotalPrice;
}
Queries that I tried:
#Query(value = "select orders.order_id, orders.amount, orders.created_date, orders.status, orders.user_id, " +
"orders.user_name from orders where orders.user_id = :userid", nativeQuery = true)
List<Orders> selectAllOrdersOfSpecificUser(#Param("userid") Long userId);
==================================================================================
List<Orders> findAllByUserId(Long userId);
Both of them bring all the records from the orders table and associated records in the order detail table.
FetchType.EAGER will retrive all the orderdetails as well. Use FetchType.LAZY and create a special JOIN FETCH query for getting orderdetails with orders.

Spring: Persisting a list of attributes which has list of other attributes in itself

I am trying to make webservice for food order management . I have a Entities Product and Restaurant and I am struggling to make Order Entity .
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
#JoinColumn(name = "restaurant_id", referencedColumnName = "id", insertable=false, updatable=false)
#JsonBackReference
private Restaurant restaurant;
private int restaurant_id;
private String name;
private float price;
}
#Entity
public class Restaurant {
#Id
#GeneratedValue
private int id;
#NotNull
private String name;
private String city;
private String phone;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "restaurant", cascade = CascadeType.ALL)
#JsonManagedReference
private List<Product> menu;
}
I want the Order entity to have a List. If i keep an attribute OrderId in Product , to Join tables Product and Order, will that be a good idea? Is there any better way to do it?
PS: I don't want to keep order Id with Product because i think Product should not be aware of it
Yes, that's a fine idea.
You can use List in Order entity and join them by having id of order in product.
it's kinda hard to tell what you really want, but this site (under headline relationships) has description of best practices for likely to all of your use cases!
https://vladmihalcea.com/tutorials/hibernate/
Cheers!

Spring data JPA join table with extra column

I'm trying to implement a meeting model which contains multiple equipment entity with corresponding quantity.
In the view of meeting, user should be able to CRUD equipment and quantity of this equipment of a meeting
databases:
CREATE TABLE IF NOT EXISTS equipment (
equipment_id SERIAL PRIMARY KEY,
equipment_name VARCHAR(20) NOT NULL
);
CREATE TABLE IF NOT EXISTS meeting (
meeting_id SERIAL PRIMARY KEY,
meeting_time TIMESTAMP NOT NULL,
number_people INTEGER NOT NULL,
setup VARCHAR(255)
);
CREATE TABLE IF NOT EXISTS meeting_equipment (
meeting_equipment_id SERIAL PRIMARY KEY ,
meeting_id INTEGER NOT NULL REFERENCES meeting (meeting_id),
equipment_id INTEGER NOT NULL REFERENCES equipment (equipment_id),
quantity INTEGER NOT NULL DEFAULT 0
);
Entity implementation:
#Entity
#Table(name = "meeting")
#Data
public class Meeting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "meeting_id", updatable = false)
#JsonIgnore
private int id;
#Column(name = "meeting_time")
#JsonFormat(pattern = "yyyy-MM-dd HH:mm")
#NotNull
private LocalDateTime meetingTime;
#Column(name = "number_people")
#NotNull
#Min(1)
private int numberPeople;
#Column(name = "setup")
#NotNull
private String setup;
#OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL)
#JsonManagedReference
List<MeetingEquipment> equipmentList = new ArrayList<>();
}
#Entity
#Table(name = "equipment")
#Data
public class Equipment {
#Id
#Column(name = "equipment_id", updatable = false)
#JsonIgnore
private int id;
#NotNull
#Column(name = "equipment_name", unique = true)
#Size(min = 1, max = 100)
private String equipmentName;
}
Join table metting_equipment:
#Entity
#Table(name = "meeting_equipment", uniqueConstraints = {
#UniqueConstraint(columnNames = {"meeting_id", "equipment_id"})})
#Data
public class MeetingEquipment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "meeting_equipment_id", updatable = false)
#JsonIgnore
private int id;
#ManyToOne
#JoinColumn(name = "meeting_id")
#NotNull
#JsonBackReference
private Meeting meeting;
#ManyToOne
#JoinColumn(name = "equipment_id")
#NotNull
private Equipment equipment;
#Column(name = "quantity")
#NotNull
private int quantity;
}
Using the code above, I can successfully create meeting with equipment included (JSON returned from creation method shows correct content). But once I try to remove an element of equipmentList in meeting entity, it does not delete meetingEquipment entity. I tried
meeting.getEquipmentList().clear() and meetingEquipmentDao.delete(meeting.getEquipmentList()), neither works.
Could anyone tell me the cause of this problem, thanks!

Record not inserted while using #ManyToOne mapping

I have 2 tables 'orders' and 'orderlines' and used bidirectional OneToMany mapping.When i save the order, record is successfully inserted into table 'orders'.But my 'orderlines' table is empty.No record is inserted.
This is the save operation code in Controller.
#RequestMapping(value = "ordersuccess", method = RequestMethod.POST)
public String processOrder(#ModelAttribute("order") Order order,
#ModelAttribute("cart") Cart cart,
BindingResult result) {
if (!result.hasErrors()) {
Set<OrderLine> orderLines = new HashSet<OrderLine>();
for(CartLine c : cart.getCartLines()) {
OrderLine line = new OrderLine();
line.setOrder(order);
line.setProduct(c.getProduct());
line.setProductPrice(c.getProduct().getPrice());
line.setTotalPrice(c.getPrice());
orderLines.add(line);
order.setOrderLines(orderLines);
}
orderService.save(order);
orderLineService.save(orderLine);
}
return "ordersuccess";
}
Can someone point me what wrong i am doing.
EDIT:
OrderLine.java
public class OrderLine {
#Id
#GeneratedValue
#Column(name="orderline_id")
private int orderline_id;
#ManyToOne
#JoinColumn(name = "order_id")
private Order order;
#ManyToOne(targetEntity = Product.class,
cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
#JoinTable(
name="products",
joinColumns=#JoinColumn(name="product_id")
)
private Product product;
)
Order.java
public class Order {
#Id
#GeneratedValue
#Column(name="id")
private int id;
#OneToMany(mappedBy = "order")
private Set<OrderLine> orderLines;
//getter/setter
The orderLines object is created:
Set<OrderLine> orderLines = new HashSet<OrderLine>();
You then add lines to it:
orderLines.add(line);
But it never attributed to an order or sent to the service layer.
Also the OrderLine.product mapping should be like this
public class OrderLine {
#Id
#GeneratedValue
#Column(name="orderline_id")
private int orderline_id;
#ManyToOne
#JoinColumn(name = "order_id")
private Order order;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "product_id")
private Product product;
}
and Order.orderLines should have a cascade:
public class Order {
#Id
#GeneratedValue
#Column(name="id")
private int id;
#OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private Set<OrderLine> orderLines;
}
You then need to save the orderLines:
order.setOrderLines(orderLines);
and save the order:
orderService.save(order);
When order is saved it will cascade the orderlines and the associated product too.
If you have bidirectional associations don't forget to set both sides.

Resources