0% found this document useful (0 votes)
1 views

Module 06 - Hibernate Complex Mapping-upd

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Module 06 - Hibernate Complex Mapping-upd

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Module 06: Complex Mapping

CS544: Enterprise Architecture

© 2014 Time2Master 1
Complex Mappings
 In this module we will cover:
 Secondary tables – allow a class to be mapped to
multiple tables
 Embedded classes – allow multiple classes to be
mapped to a single table
 Composite keys – can be made using embedded
classes
 Immutable entities – Hibernate can optimize for
entities that never change

© 2014 Time2Master 2
Complex Mapping

SECONDARY TABLES

© 2014 Time2Master 3
Secondary Tables
 Secondary tables can be used anywhere to
move properties into separate table(s)
 To do so, the property has to specify the table
 Secondary tables can even be used in combination
with the Single table inheritance strategy
Secondary table used in an
@Entity inheritance hierarchy
@DiscriminatorValue("savings")
@SecondaryTable(
name="SavingsAccount",
pkJoinColumns=@PrimaryKeyJoinColumn(name="number")
)
public class SavingsAccount extends Account {
@Column(table="SavingsAccount")
private double APY;
Property specifies that it should
... be on the SavingsAccount table

© 2014 Time2Master 4
Secondary Table
@SecondaryTables can specify
multiple @SecondaryTable pkJoinColumns can be used to
@Entity specify a multi column join
@SecondaryTables(
@SecondaryTable(name="warehouse", pkJoinColumns = {
@PrimaryKeyJoinColumn(name="product_id", referencedColumnName="number")
}
))
public class Product { JoinColumn name can differ
@Id from the referenced column
@GeneratedValue
private int number;
private String name;
private BigDecimal price; Properties need to
@Column(table="warehouse") specify the secondary
private boolean available; table to be on it All you really need is @SecondaryTable
and a name, the rest is optional
... @Entity
@SecondaryTable(name="warehouse")
public class Product {
@Id
Product
@GeneratedValue
private int number;
+number
+name private String name;
+price private BigDecimal price;
+available
@Column(table = "warehouse")
private int available;

...
© 2014 Time2Master 5
XML
<hibernate-mapping package="join_tables">
<class name="Product">
<id name="number">
<generator class="native" />
</id>
<property name="name" />
<property name="price" />
<join> tag to specify the table
<join table="warehouse">
<key column="product_id" /> Requires <key> to specify
<property name="available" /> the pk join column
</join>
</class>
</hibernate-mapping>

Product Table

Product

+number
+name
+price
+available
Warehouse Table

© 2014 Time2Master 6
Complex Mapping

EMBEDDED CLASSES

© 2014 Time2Master 7
Embedded Classes
 Combine multiple classes in a single table
 Especially useful for tight associations
 These classes are considered value classes
rather than entity classes
Address is embedded
inside the Person table

Address
Person
lives at +street
+firstname +city
+lastname 1 1 +state
+zip

© 2014 Time2Master 8
Embeddable
@Embeddable
instead of @Entity
@Entity @Embeddable
public class Person { public class Address {
@Id private String street;
@GeneratedValue private String city;
private int id; private String state;
@Embedded private String zip;
private String firstname;
annotation is private String lastname;
used for ... No @Id in embeddable
embeddable @Embedded
objects private Address address;

...

Address
Person
lives at +street
+firstname +city
+lastname 1 1 +state
+zip

© 2014 Time2Master 9
XML
<hibernate-mapping package="embedded">
<class name="Person">
<id name="id">
<generator class="native" />
</id>
<property name="firstname" />
<property name="lastname" />
<component> tag indicates
<component name="address" class="Address"> an embedded object
<property name="street" />
<property name="city" />
<property name="state" />
<property name="zip" />
</component>
</class>
</hibernate-mapping>

Address
Person
lives at +street
+firstname +city
+lastname 1 1 +state
+zip

© 2014 Time2Master 10
Multiple Embedded Addresses
@Entity
public class Customer {
@Id
@GeneratedValue
private int id;
private String firstname; Rename the column names
private String lastname; for the embedded object
@Embedded
using @AttributeOverrides
@AttributeOverrides( {
@AttributeOverride(name="street", column=@Column(name="ship_street")),
@AttributeOverride(name="city", column=@Column(name="ship_city")),
@AttributeOverride(name="state", column=@Column(name="ship_state")),
@AttributeOverride(name="zip", column=@Column(name="ship_zip"))
})
private Address shipping;

@Embedded
@AttributeOverrides( {
@AttributeOverride(name="street", column=@Column(name="bill_street")),
@AttributeOverride(name="city", column=@Column(name="bill_city")),
@AttributeOverride(name="state", column=@Column(name="bill_state")),
@AttributeOverride(name="zip", column=@Column(name="bill_zip"))
})
private Address billing;

... © 2014 Time2Master

11
Multiple Addresses XML
<hibernate-mapping package="embedded">
<class name="Customer">
<id name="id">
<generator class="native" />
</id>
<property name="firstname" />
<property name="lastname" />

<component name="shipping" class="Address">


<property name="street" column="ship_street" /> You can specify the column
<property name="city" column="ship_city" /> name using the column
<property name="state" column="ship_state" /> attribute on <property>
<property name="zip" column="ship_zip" />
</component>

<component name="billing" class="Address">


<property name="street" column="bill_street" />
<property name="city" column="bill_city" />
<property name="state" column="bill_state" />
<property name="zip" column="bill_zip" />
</component>
</class>
</hibernate-mapping>

© 2014 Time2Master 12
Complex Mapping

COMPOSITE KEYS

© 2014 Time2Master 13
Composite Keys
 Composite Keys are multi-column Primary Keys
 By definition these are natural keys
 Have to be set by the application (not generated)
 Generally found in legacy systems
 Also create multi-column Foreign Keys

 There are several different mapping strategies:


 Most common mapping uses an embeddable class as
the composite key
 Other mappings are not supported by both annotations
and XML (either one or the other)

© 2014 Time2Master 14
Composite Ids
@Embeddable
@Embeddable
public class Name {
private String firstname;
private String lastname;

... Also requires hashCode and equals methods


(see next slide)

@Entity
public class Employee { Embeddable object as identifier
@EmbeddedId creates composite key
private Name name;
@Temporal(TemporalType.DATE)
private Date startDate;

...

PK is made of
Both firstname
and lastname

© 2014 Time2Master 15
equals() & hashCode()
@Embeddable
public class Name {
private String firstname;
private String lastname;

...
Compares object
public boolean equals(Object obj) { contents for equality
if (this == obj)
return true;
if ((obj == null) || obj.getClass() != this.getClass())
return false;
Name n = (Name) obj;
if (firstname == n.firstname || (firstname != null && firstname.equals(n.firstname))
&& lastname == n.lastname || (lastname != null && lastname.equals(n.lastname))) {
return true;
} else {
return false;
}
}
Generates an int based on
public int hashCode() { the class contents
int hash = 1234;
if (firstname != null)
hash = hash + firstname.hashCode();
if (lastname != null)
hash = hash + lastname.hashCode();
return hash;
}
© 2014 Time2Master 16
XML
<hibernate-mapping package="composite_key">
<class name="Employee">
<composite-id name="name" class="Name"> <composite-id> tag is used
<key-property name="firstname" /> in XML to specify the
<key-property name="lastname" /> property and class name
</composite-id>

<property name="startDate" type="date"/>


</class>
</hibernate-mapping>

PK is made of
Both firstname
and lastname

© 2014 Time2Master 17
Foreign Keys to Composite Ids
@Entity
public class Employee { Same Name embeddable
@EmbeddedId @Id as before
private Name name;
@Temporal(TemporalType.DATE)
private Date startDate; Normal mappedBy on this side
@OneToMany(mappedBy = "owner")
private List<Project> projects = new ArrayList<Project>();

...

@Entity
public class Project { Two column
@Id
Foreign Key
@GeneratedValue
private int id;
private String name;
@ManyToOne
@JoinColumns( {
@JoinColumn(name = "Emp_firstname", referencedColumnName = "firstname"),
@JoinColumn(name = "Emp_lastname", referencedColumnName = "lastname")
})
private Employee owner;
Two column FK
... specification

© 2014 Time2Master 18
XML Composite FK
<hibernate-mapping package="composite_key">
<class name="Employee">
<composite-id name="name" class="Name">
<key-property name="firstname" />
<key-property name="lastname" />
</composite-id>
<property name="startDate" type="date" /> Even though the collection
is inverse we still need to
<bag name="projects" inverse="true"> specify both columns
<key>
<column name="Emp_firstname" />
<column name="Emp_lastname" />
</key> Using <column> tags inside <key>
<one-to-many class="Project" /> instead of the column attribute on <key>
</bag>
</class>
</hibernate-mapping>

<hibernate-mapping package="composite_key">
<class name="Project">
<id name="id">
<generator class="native" />
</id>

<many-to-one name="owner" class="Employee">


<column name="Emp_firstname" />
<column name="Emp_lastname" />
</many-to-one> Using <column> tags inside <many-to-one>
</class> instead of the column attribute on it
</hibernate-mapping>
© 2014 Time2Master 19
Complex Mapping

ELEMENT COLLECTIONS

© 2014 Time2Master 20
Element Collections
 For collections of primitive values or
collections of embeddables

 Does not really make sense from a OO / UML


point of view

 Good to know about

© 2014 Time2Master 21
@ElementCollection
@Entity
public class Person { Optionally specify the name
@Id @GeneratedValue for the collection table
private int id;
@ElementCollection
@CollectionTable(name = "firstNames")
private List<String> givenNames = new ArrayList<>();
@ElementCollection
@CollectionTable(name = "lastNames")
private List<String> familyNames = new ArrayList<>();
@ElementCollection
private List<Address> addresses = new ArrayList<>();
...

Default table name is:


Classname_propertyname

© 2014 Time2Master 22
Map

@Entity
public class Person {
@Id @GeneratedValue
Optionally specify the name
private int id;
private String name; for the additional key column
@ElementCollection
@MapKeyColumn(name = "name")
private Map<String, Pet> Pets = new HashMap<>();
...

Default key column name is:


propertyname_KEY

© 2014 Time2Master 23
Complex Mapping

IMMUTABLE ENTITIES

© 2014 Time2Master 24
Immutable Entities
 An immutable entity is an entity that
 Once created, does not change – no updates
 Hibernate can perform several optimizations

 A Java immutable class:


 Only has getters methods, no setters
 Sets all fields in the constructor
 Gives Hibernate field access

© 2014 Time2Master 25
Immutability
@Entity
@org.hibernate.annotations.Entity(mutable=false) Set mutable false using
public class Payment { Hibernate Entity extension
@Id Field access through
@GeneratedValue placement of @Id
private final int id;
private final double amount;
@Column(name="`to`")
private final String to;
@Column(name="`from`")
private final String from;
Data is set in constructor
public Payment() {}
public Payment(double amount, String to, String from) {
this.amount = amount;
this.to = to;
this.from = from;
} Getters, but no Setters
public int getId() { return id; }
public double getAmount() { return amount; }
public String getTo() { return to; }
public String getFrom() { return from; }
}

© 2014 Time2Master 26
XML

Default Field access

<hibernate-mapping package="immutable" default-access="field">


<class name="Payment" mutable="false">
<id name="id">
<generator class="native" /> Mutable = false
</id>
<property name="amount" />
<property name="to" column="`to`" />
<property name="from" column="`from`"/> (To and From are SQL keywords)
</class>
</hibernate-mapping>

© 2014 Time2Master 27
Active Learning
 What is a value class?

 Why do we need to implement hashcode()


and equals() when using @EmbeddedId?

© 2014 Time2Master 28
Module Summary
 In this module we covered some of the more
interesting mappings possible with Hibernate
 Many of these mappings are very useful when
mapping to a legacy database
 Embeddable components also have their place
in non-legacy systems
 Allow a fine-grained object model to be mapped
to a more coarse and efficient db model
 Sacrifices some flexibility for greater efficiency

© 2014 Time2Master 29

You might also like