Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setting the correct jpa mapping for shopping cart items and product

I am learning jpa through some examples ,involving a shopping cart and cart items.I defined them as below..but am not very sure about which mapping to use

@Entity
class Product{

   private Long id;
   private String name;
   ...
}

@Entity
class CartItem{
   private Long id;

   private Product product;

   private int quantity;

...
}

@Entity
class ShoppingCart{
   private Long id;

   @OneToMany
   private Set<CartItem> cartItems;

  ...
}

What I am not very sure of ,is how to relate between Product and CartItem and how to set the mappedBy attribute.Can somebody tell me how to do this?What are the criteria in doing this?I was trying to set something like 1 cartitem contains 1 product only.It sounds like a OneToOne relation.If so, who maintains the relation(is that not what mappedBy does?).I have similar doubt about ShoppingCart and CartItems too

thanks in advance

like image 566
jonlannister Avatar asked Sep 05 '11 13:09

jonlannister


People also ask

How is JPA mapping done?

Association mappings are one of the key features of JPA and Hibernate. They model the relationship between two database tables as attributes in your domain model. That allows you to easily navigate the associations in your domain model and JPQL or Criteria queries.

What is JPA mapping?

The One-To-One mapping represents a single-valued association where an instance of one entity is associated with an instance of another entity. In this type of association one instance of source entity can be mapped atmost one instance of target entity.


2 Answers

One cart item references one product. But a single product is referenced by several cart items. So it's a one-to-many association.

One shopping cart as several items, and an item is part of one shopping cart, so it's also a one-to-many association.

When you have a bidirectional OneToMany association, the owner side of the association is always the many side. The owner side of an association is the side where there is no mappedBy attribute. Indeed, mappedBy means "I'm just the other side of an association, which is already mapped by the following attribute". Note that the way the asociation is mapped (join column, join table) must only be defined on the owner side, where the mappedBy attribute is absent.

When you have a unidirectional association, there is only one place where the mapping can be defined, and the mappedBy attribute is thus never used.

So, your entities should be mapped like this:

@Entity
class Product{

   private Long id;
   private String name;
   ...
}

@Entity
class CartItem{
   private Long id;

   @ManyToOne
   private Product product;

   private int quantity;

...
}

@Entity
class ShoppingCart{
   private Long id;

   @OneToMany
   private Set<CartItem> cartItems;

  ...
}

If you want your cart item to know about its owning shopping cart, your association becomes bidirectional, and the entities become:

@Entity
class CartItem{
   private Long id;

   @ManyToOne
   private Product product;

   @ManyToOne
   private ShppingCart shoppingCart;

   private int quantity;

...
}

@Entity
class ShoppingCart{
   private Long id;

   @OneToMany(mappedBy = "shoppingCart")
   private Set<CartItem> cartItems;

  ...
}
like image 66
JB Nizet Avatar answered Sep 23 '22 11:09

JB Nizet


You ought to first decide whether you want a unidirectional or a bidirectional @OneToOne relationship. A unidirectional relationship has an owning side (the side where the reference to another class is present), while a bidirectional relationship has both an owning side and an inverse side.

If you are declaring a unidirectional @OneToOne relationship, then you do not need to worry about the mappedBy attribute. For example, if you declare the Product-CartItem relationship as a unidirectional relationship with the CartItem owning the relationship (and also possessing the foreign key in the database), then you merely need to annotate a reference to the Product in the Product class, as shown below; no changes are required in the Product class:

@Entity
class CartItem{
   private Long id;

   @OneToOne
   private Product product;

   private int quantity;

...
}

If you need a bi-directional relationship, then you must define references that go both ways. In this case, you'll need to add a reference to a CartItem from the Product class. Furthermore, you'll need to specify the mappedBy attribute on the inverse side, to refer to the owning side (the side that has the foreign key in the database), as shown below:

@Entity
class Product{

   private Long id;
   private String name;
   @OneToOne(mappedBy="product") // the name of the property in the owning side
   private CartItem cartItem;
   ...
}

@Entity
class CartItem{
   private Long id;

   @OneToOne                    //the owning side
   private Product product;

   private int quantity;

...
}
like image 27
Vineet Reynolds Avatar answered Sep 24 '22 11:09

Vineet Reynolds