Suresh Rohan's Blog

This blog is all about Java, J2EE,Spring, Angular, React JS, NoSQL, Microservices, DevOps, BigData, Tutorials, Tips, Best practice, Interview questions, Views, News, Articles, Techniques, Code Samples, Reference Application and much more

Monday, July 8, 2013

Hibernate Mapping Cardinality & Inheritance Relationships Tutorial

Topics

• Mapping cardinality relationship
       – One-To-Many
       – Many-To-Many
       – One-has-Map
• Mapping inheritance relationship
       – One table per each concrete class implementation
       – One table for each subclass
       – One table for each class hierarchy


Mapping Cardinality Relationship

● one-to-one
● many-to-one
● one-to-many
● many-to-many

One to One Relationship

● Expresses a relationship between two classes where each instance of the first class
is related to a single instance of the second or vice versa
● Can be expressed in the database in two ways
         – Giving each of the respective tables the same primary key values
         – Using foreign key constraint from one table onto a unique identifier column of the other

Mapping Cardinality Relationship: One-To-Many

One-To-Many Relationship
1.<set>
2.<list>
3.<array>

4.<bag>

One-To-Many: Using <set>

1. One-to-Many relationship: Using <set> in mapping file

● An event has many speakers and attendees
● Event.hbm.xml

<class name="Event" table="events">
<id name="id" column="uid" type="long" unsaved-value="null">
<generator class="increment"/>
</id>
<property name="name" type="string" length="100"/>
<set name="speakers" cascade="all">
<key column="event_id"/>
<one-to-many class="Speaker"/>
</set>
<set name="attendees" cascade="all">
<key column="event_id"/>
<one-to-many class="Attendee"/>
</set>

</class>'

One to Many relationship: Using Set in Domain Class 

● An event has many speakers and attendees

public class Event {
private Long id;
private String name;
private Date startDate;
private int duration;
// Event has one-to-many relationship with Speaker
private Set speakers;
// Event has one-to-many relationship with Attendee
private Set attendees;

// ...

Creating Object Instance

● An event has many speakers and attendees

// Create an Event object which has one to many relationship
// with Speaker objects.
Event event = new Event();
event.setName("Java Conference");
event.setSpeakers(new HashSet());
event.getSpeakers().add(new Speaker("Sang", "Shin"));
event.getSpeakers().add(new Speaker("Dave", "Smith"));
event.getSpeakers().add(new Speaker("Bill", "Clinton"));

session.saveOrUpdate(event);


One-To-Many: Using <list>

2. One to Many relationship: Using <list> in mapping file

● Group has many stories
● Group.hbm.xml

<class name="Group" table="grouptable">
<id name="id" unsaved-value="0">
<generator class="increment" />
</id>
<list name="stories" cascade="all">
<key column="parent_id" />
<!-- index in a single list -->
<index column="idx" />
<one-to-many class="Story" />
</list>
<property name="name" type="string" />

</class>


One to Many relationship: Using List in Domain Class

● Group has many stories

public class Group {
private int id;
private String name;
private List stories;
public void setStories(List l) {
stories = l;
}
public List getStories() {
return stories;
}

// ...

Creating Object Instances

● Group has many stories

ArrayList list = new ArrayList();
list.add(new Story("Tom Jones"));
list.add(new Story("Beatles"));
list.add(new Story("Elvis"));
Group sp = new Group("Singers");
sp.setStories(list);
ArrayList list2 = new ArrayList();
list2.add(new Story("Bill Clinton"));
list2.add(new Story("Ronald Reagan"));
Group sp2 = new Group("Politicians");

sp2.setStories(list2);

● Tables



One-To-Many: Using <array>

3. One to Many relationship: Using <array> in mapping file

● Group has many stories
● Group.hbm.xml

<class name="Group" table="grouptable">
<id name="id" unsaved-value="0">
<generator class="increment"/>
</id>
<array name="stories" cascade="all">
<key column="parent_id"/>
<index column="idx"/>
<one-to-many class="Story"/>
</array>
<property name="name" type="string"/>

</class>

One to Many relationship: Using an array in Domain Class

● Group has many stories

public class Group {
private int id;
private String name;
// Group object has an array of Story objects
private Story[] stories;
public void setStories(Story[] l) {
stories = l;
}
public Story[] getStories() {
return stories;
}

// ...

Creating an Object Instance

● Group has many stories
// Create an Group object which has one to many relationship
// with Story objects.
Group sp = new Group("Group Name");
sp.setStories(new Story[]{new Story("Story Name 1"), new

Story("Story Name 2")});

One-To-Many: Using <bag>

4. One to Many relationship: Using <bag> in mapping file

● Group has many stories
● Group.hbm.xml

<class name="Group" table="grouptable">
<id name="id" unsaved-value="0">
<generator class="increment"/>
</id>
<bag name="stories" cascade="all">
<key column="parent_id"/>
<one-to-many class="Story"/>
</bag>
<property name="name" type="string"/>
</class>

One to Many relationship: Using an List in Domain Class

● Group has many stories
public class Group {
private int id;
private String name;
private List stories;
public void setStories(List l) {
stories = l;
}
public List getStories() {
return stories;
}

// ...

Creating an Object Instance

● Group has many stories

// Create an Group object which has one to many relationship
// with Story objects.
ArrayList list = new ArrayList();
list.add(new Story("Story Name 1"));
list.add(new Story("Story Name 2"));
Group sp = new Group("Group Name");

sp.setStories(list);


Mapping Cardinality Relationship: Many-To-Many

Many to Many relationship

● Speakers speak in many events and Event has many speakers
● SpeakerManyToMany.hbm.xml

<class name="SpeakerManyToMany" table="m_speakers">
<id name="id" column="uid" type="long">
<generator class="increment"/>
</id>
<property name="firstName" type="string" length="20"/>
<property name="lastName" type="string" length="20"/>
<set name="events" table="event_speakers" cascade="all">
<key column="speaker_id"/>
<many-to-many class="EventManyToMany"/>
</set>

</class>

● Event has many speakers and speakers speak in many events
● EventManyToMany.hbm.xml

<class name="EventManyToMany" table="m_events">
<id name="id" column="uid" type="long" unsaved-value="null">
<generator class="increment"/>
</id>
<property name="name" type="string" length="100"/>
<property name="startDate" column="start_date"
type="date"/>
<property name="duration" type="integer"/>
<set name="speakers" table="event_speakers" cascade="all">
<key column="event_id"/>
<many-to-many class="SpeakerManyToMany"/>
</set>

</class>

● Event has many speakers

public class EventManyToMany {
private Long id;
private String name;
private Date startDate;
private int duration;
private Set speakers;
private Set attendees;
public void setSpeakers(Set speakers) {
this.speakers = speakers;
}
public Set getSpeakers() {
return speakers;
}

// ...

● A speaker speaks in many events

public class SpeakerManyToMany {
private Long id;
private String firstName;
private String lastName;
private Set events;
public Set getEvents() {
return this.events;
}
public void setEvents(Set events) {
this.events = events;
}

// ...

Many to Many relationship: Creating object instances

● Event has many to many relationship with Speaker

// Event has Many-To-Many relationship with Speaker
EventManyToMany event = new EventManyToMany();
event.setName("JavaOne conference");
event.setSpeakers(new HashSet());
event.getSpeakers().add(new SpeakerManyToMany("Sang", "Shin", event));
event.getSpeakers().add(new SpeakerManyToMany("Joe", "Smith", event));
event.getSpeakers().add(new SpeakerManyToMany("x", "Man", event));
// Save event

session.save(event);



Mapping Cardinality Relationship: Using <map>

One-Has-Collection relationship: Using <map> in mapping file
● SupportProperty class has Collection
● SupportProperty.hbm.xml

<class name="SupportProperty" table="supportproperty">
<id name="id">
<generator class="increment"/>
</id>
<map name="properties">
<key column="id"/>
<index column="property_name" type="string"/>
<element column="property_value" type="string"/>
</map>
<property name="name" type="string"/>

</class>

One-Has-Collection relationship: Domain Class

● Group has many stories

public class SupportProperty {
private int id;
private String name;
private Map properties;
public void setProperties(Map m) {
properties = m;
}
public Map getProperties() {
return properties;
}

// ...

Creating an Object Instance

● Group has many stories
// Create Domain object, SupportProperty object has a Map
// object.
SupportProperty sp = new SupportProperty();
sp.setName("Joe");
HashMap p = new HashMap();
p.put("color", "blue");
p.put("lnf", "mac");

sp.setProperties(p);

Mapping Inheritance: 3 Different Ways


Inheritance Relationship Representations

● 3 different ways
          – One table for each class hierarchy
          – One table for each subclass
          – One table per each concrete class implementation
● Each of these techniques has different costs and benefits

Mapping Inheritance: 1 Table for the Class Hierarchy

One Table per Class Hierarchy

● A single table for the whole class hierarchy
● Discriminator column contains key to identify the base type
● Advantages
        – Offers best performance even for in the deep hierarchy since single select may suffice
● Disadvantages
        – Changes to members of the hierarchy require column to be altered, added or removed from the table 
● How to define the mapping
        – Use <subclass> element with extends and discriminator-value attributes

<hibernate-mapping>
<subclass name="SpecialEditionBook" extends="Book" discriminator-value="SpecialEditionBook">
<property name="newfeatures" type="string" />
</subclass>

</hibernate-mapping>


Mapping Inheritance: 1 Table for Subclass

One Table per Subclass
● One table for each class in the hierarchy
         – Foreign key relationship exists between common table and subclass tables
● Advantages
         – Does not require complex changes to the schema when a single parent class is modified
         – Works well with shallow hierarchy
● Disadvantages
         – Can result in poor performance – as hierarchy grows, the number of joins required to construct a leaf class also grows

● How to define the mapping
         – Use <joined-subclass> element with extends attribute in the mapping file of the subclass

Example: One Table per Subclass

<hibernate-mapping>
<joined-subclass name="SpecialEditionBook"
extends="Book"
table="secd">
<key column="id" />
<property name="newfeatures" type="string" />
</joined-subclass>
</hibernate-mapping>




Mapping Inheritance: 1 Table for Concrete Class

One Table per Concrete Class
● Map each of the concrete classes as normal persistent class
● Pros
      – Easiest to implement
● Cons
      – Data belonging to a parent class is scattered across a number of different tables, which represent concrete classes
      – A query couched in terms of parent class is likely to cause a large number of select operations
      – Changes to a parent class can touch large number of tables
      – This scheme is not recommended for most cases

● How to define the mapping
     – The mapping of the subclass repeats the properties of the parent class

One Table per Concrete Class

<hibernate-mapping>
<class name="Book" table="cd" discriminator-value="cd">
<id name="id" type="integer" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
</class>
<class name="SpecialEditionBook" table="secd">
<id name="id" type="integer" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
<property name="newfeatures" type="string"/>
</class>

</hibernate-mapping>



Thank You!

No comments:

Post a Comment