Relationship Pair

Most often we can think of @OneToMany and @ManyToOne as a pair representing 2 sides of a relationship. As such @OneToMany has the "many" side of the relationship and @ManyToOne has the "one" side of the relationship.

mappedBy

The mappedBy attribute should be defined in most @OneToMany. The mappedBy attribute effectively refers to the other side of the relationship.

Example: Customer has many Contacts

@Entity
public class Customer ...

  // mappedBy referring to the other side of this relationship
  @OneToMany(mappedBy="customer")
  List<Contact> contacts;
  ...

On the other side of the relationship in the Contact entity bean we define the @ManyToOne property that the mappedBy refers to.

@Entity
public class Contact ...

  // the customer property referred to by @OneToMany(mappedBy="customer")
  @ManyToOne(optional=false)
  Customer customer;
  ...

Bi-directional

When we map both sides of the relationship with a @OneToMany and @ManyToOne pair we can describe this as a bi-directional relationship. The relationship can be viewed, navigated and loaded from both directions.

There are no restrictions or limitations when we have a bi-directional relationship.

Not mapping the @OneToMany

The reason we might choose to not map the @OneToMany side of a relationship is when the cardinality is high (say thousands) and we deem that we never want to allow the application to navigate the relationship in that direction as doing so naively might load too many of objects.

For example if a Customer had 1 million Orders and we naively navigated from that Customer to all their orders we could load 1 millions Order instances into memory which is generally something we don't want to do. In this case we could use filterMany on a Customer query to filter the orders for each customer (e.g. orders created in the last week). Alternatively we can load the graph in the other direction (From Order to Customer).

Omitting a @OneToMany effectively means we can't navigate or load the relationship from that direction and instead it forces the application to always use the other direction (to build object graphs).

Not mapping the @ManyToOne

When we do not map the @ManyToOne this adds a restriction and implies an ownership relationship.

For example take the case of Order having many OrderDetail. When we don't map the @ManyToOne side in OrderDetail:

Order has details:

@Entity
@Table(name = "orders")
public class Order ...

  // we MUST have cascade persist here for this
  // unidirectional case (no @ManyToOne)
  @OneToMany(cascade = CascadeType.ALL)
  List<OrderDetail> details;
  ...

OrderDetail has no matching @ManyToOne:

@Entity
public class OrderDetail ...

  // Does not have - @ManyToOne(optional = false) Order order;

This effectively adds the restriction that to insert new OrderDetails we must cascade persist from Order to do so. That is, the @ManyToOne effectively represents the foreign key column that is on the underlying table for OrderDetail and to populate that foreign key column we must use cascade persist from Order.

This also implies that the foreign key value can never change and hence we can view this conceptually as an 'ownership' relationship. In this example each OrderDetail is 'owned' by an Order.

Personally I always map the @ManyToOne