Ok so today I have spent all day trying to figure out how to map a relationship between Orders, Products, and OrderLine with hibernate using annotations all java config.
I want OrderLine to be a junction table with extra fields, that joins Products and Orders.
Orders has a OneToMany relationsbhip with OrderLine - One order has many order lines.
Each Order has one or more OrderLines, Each OrderLine has one Order, Each OrderLine has one Product, Each Product can have 0 or more OrderLines.
From what I have been following along with tutorials, there are two ways to do it. One being with @Embeddable, @EmbeddedId annotations and the other being @IdClass annotations, I have tried both with no success I will post my code for my shot at @IdClass method.
My orders class
@Entity
@Table(name="orders")
public class Order {
@Id
@Column(name = "order_id")
@OneToMany(fetch = FetchType.EAGER, mappedBy = "order")
private Set<OrderLine> orderLines = new HashSet<>();
...some extra properties relevant to all orders
public Order(){}
...setters/getters
}
My Products class
@Entity
@Table(name="products")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "product_id")
public Integer product_id; // primary key
@OneToMany(fetch = FetchType.EAGER, mappedBy = "product")
private Set<OrderLine> orderLines = new HashSet<>();
...other properties
public Product() {
}
...setters/getters
}
Here is my OrderLine Class
@Entity
@IdClass(OrderLineId.class)
@Table(name="order_line")
public class OrderLine implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "product_id", insertable= false, updatable= false)
public Integer product_id;
@Id
@Column(name = "order_id", insertable= false, updatable= false)
public Integer order_id;
@ManyToOne
@JoinColumn(name = "product_id", insertable = false, updatable = false)
private Product product;
@ManyToOne
@JoinColumn(name = "order_id", insertable = false, updatable = false)
private Order order;
@Column(name = "product_quantity", unique = false, nullable = false)
private int productQuantity;
...additional fields associated with each OrderLine
And finally my OrderLineId implementation
public class OrderLineId implements Serializable {
private static final long serialVersionUID = 1L;
private Integer order_id;
private Integer product_id;
public OrderLineId(){}
public OrderLineId(Integer order_id, Integer product_id) {
this.order_id = order_id;
this.product_id = product_id;
}
@Column(name = "order_id")
public Integer getOrder() {
return this.order_id;
}
public void setOrder(Integer order_id) {
this.order_id = order_id;
}
@Column(name = "product_id")
public Integer getProduct() {
return this.product_id;
}
public void setProduct(Integer product_id) {
this.product_id = product_id;
}
@Override
public int hashCode() {
return order_id + product_id;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof OrderLineId){
OrderLineId orderLineId = (OrderLineId) obj;
return orderLineId.order_id == order_id && orderLineId.product_id == product_id;
}
return false;
}
}
Here is the exception I am getting
MySQLSyntaxErrorException: Unknown column 'orderlines0_.order' in 'field list'
when I visit the end point below
@RequestMapping(value = "/testorder", method = RequestMethod.GET)
public ModelAndView testOrder(){
Order order = orderService.findOrderById(23);
Product product = productService.findProduct(2);
OrderLine ol = new OrderLine(product, order);
ol.setSize("large");
ol.setProductQuantity(30);
orderService.saveOrderLine(ol);
return null;
}
Please can somebody help me, this is driving me crazy....
Thank you
Ok I figured it out - I ended up using embeddable method instead based on this guys excellent tutorial here
He goes through 3 major ways to implement many to many assosiations - a simple junction only table, a junction table (with additional fields) which is the method I needed to implement, and finally a less popular method where the class is mapped as a component.