Search code examples
javaspringhibernatehibernate-mapping

Orders Products and Order_Line Hibernate Relationship with Composite Keys


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


Solution

  • 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.