Composition as set of many classes

Full source code is provided in the package: de.laliluna.component.collection2

ClassesTables

images/c_component_collection_class.jpg

images/c_component_collection_table.jpg

Annotation mapping. 

import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
....... snip ........
@Entity
public class Pizza {
// ... snip ...

   @ElementCollection
   @CollectionTable(name="pizza_ingredients", joinColumns =
      @JoinColumn(name="pizza_id"))
   private Set<Ingredient> ingredients = new HashSet<Ingredient>();

@ElementCollection defines the component mapping. @JoinTable is optional. It specifies the name of the ingredient table and the foreign key column.

Deprecated Hibernate extension

Before Java Persistence 2 only Hibernate supported this kind of mapping. The annotation was named slightly different @CollectionOfElements and is now deprecated.

import org.hibernate.annotations.Parent;
import javax.persistence.Embeddable;

@Embeddable
public class Ingredient {

   private String name;

   @Parent
   private Pizza client;

@Parent specifies the property to be a reference back to the embedding class, i.e. PizzaClient in our case.

XML mapping. 

<hibernate-mapping package="de.laliluna.component.collection2">
<class name="Pizza" table="tclient" >
  <!-- .. snip .. ->
  <set name="ingredients" table="pizza_ingredients">
    <key column="client_fk"></key>
    <composite-element class="de.laliluna.component.collection2.Ingredient"  >
      <property name="name"/>
    </composite-element>
  </set>
</class>
</hibernate-mapping>

Samples of use:

/* create and set component */
Pizza pizza = new Pizza("Speciale");
Ingredient cheese = new Ingredient("Cheese");
Ingredient salami = new Ingredient("Salami");
Ingredient tomatoes = new Ingredient("Tomatoes");
pizza.getIngredients().add(salami);
pizza.getIngredients().add(cheese);
pizza.getIngredients().add(tomatoes);
session.save(pizza);

/* select pizza clients having an address in London */
List<PizzaClient> list = session
    .createQuery(
   "from Pizza c left join c.ingredients a where a.name = :ingr")
   .setString("ingr", "Tomato").list();