Composed class in one table

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

ClassesTables

images/c_component_simple_class.jpg

images/c_component_simple_table.jpg

In this example a soup has two components: recipe and taste. All information is kept in one table. We declare Recipe and Taste as simple properties. In their mapping we have to define that they are embeddable.

Annotation mapping. 

import java.io.Serializable;
import javax.persistence.Entity;
....... snip .......
@Entity
public class Soup  implements Serializable{

   private Taste taste;

   private Recipe recipe;

As you can see there are no @Embedded annotations. We only need them, if we want to overwrite the default values.

import java.io.Serializable;
import javax.persistence.Embeddable;
import org.hibernate.annotations.Parent;

@Embeddable
public class Recipe implements Serializable {
    private String ingredients;

    private String description;

    @Parent
    private Soup soup;

@Embeddable specifies that this class can be embedded into other entities. @Parent defines that this is a reference back to the embedding class. This is the soup in our case.

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class Taste implements Serializable {
   private String firstImpression;

   private String evaluation;

XML mapping. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="de.laliluna.component.simple">
  <class name="Soup" table="tsoup" >
........... snip ..............
    <component name="taste" class="Taste">
      <property name="firstImpression" column="first_impression"></property>
      <property name="evaluation" column="evaluation"></property>
    </component>

    <component name="recipe" class="Recipe" unique="true">
      <parent name="soup"/>
      <property name="ingredients" column="ingredients"></property>
      <property name="description" column="description"></property>
    </component>
  </class>
</hibernate-mapping>

The unique="true" causes a unique key for the database table. Ingredients and description are of course unique. If you need to access the soup from the recipe, than you can add a parent tag.

<parent name="soup"/>

In this case your recipe class must provide a soup attribute.

Samples of use:

/* create a soup */
Soup soup = new Soup("Vegetable soup");
Taste taste = new Taste();
taste.setEvaluation("best eaten so far");
taste.setFirstImpression("incredible");
soup.setTaste(taste);
Recipe recipe = new Recipe();
recipe.setDescription("wash and cut vegetables\nadd water\ncook");
recipe.setIngredients("choice of vegetables you like");
soup.setRecipe(recipe);

session.save(soup);

/* select soups where attribute evaluation of component taste
is „best eaten so far“ */
List<Soup> list = session.createQuery("from Soup s where s.taste.evaluation = ?")
   .setString(0,"best eaten so far")
   .list();