Database Applications (15-
415)
ORM - Part I
Lecture 11, February 11, 2018
Mohammad Hammoud
Today…
Last Session:
Standard Query Language (SQL) - Part III
Today’s Session:
Object Relational Mapping (ORM) - Part I
Announcements:
P1 is due on Thursday, Feb 15 by midnight
Outline
Introduction to Object Relational Mapping
Java Persistence API
Mapping Relationships
Mapping Inheritance
The Big Picture
ORM
SQL
SQL
Object Relational Mapping (ORM)
Objects are first-class citizens: “Think like an object”
Relation / Table Class
Record / Row / Tuple Object
Attribute / Column Member / Field
Relationship Composition / Aggregation
Hierarchy (Is-A) Inheritance
Objectives
Load / Persist objects (typically via a relational database)
Application stays oblivious to type of persistent storage
Combines the benefits of OOP and RDBMS
Precludes the need for writing SQL
Generates and executes DDL and DML as needed
Provides flexibility w.r.t. mapping strategies
OOP Recap
Classes and objects
Simple, structured, flexible, and popular
Classes
Encapsulation (fields and methods)
Composition / Aggregation (Has-A)
Inheritance (Is-A)
Objects
Scoped attributes and methods
(e.g., private, protected, public)
Attribute validation
(e.g., through getters and setters)
Polymorphism
Object Serialization
What to serialize?
Attributes and complex types
Composed / aggregated objects
Animal
Inherited objects
Wild Pet
Object Graph
Load/persist partially or fully?
Human
When to serialize?
Load/persist eagerly or lazily?
Outline
Introduction to Object Relational Mapping
Java Persistence API
Mapping Relationships
Mapping Inheritance
Java Persistence API (JPA)
Java standard specification for ORM
Entity = persistable object
Uses in-line code annotations for
denoting entities, attributes, relationships
fine-grained control over mappings
Multiple implementations
EclipseLink by Oracle (reference)
Hibernate by JBoss (popular)
Advanced features (e.g., distributed object cache)
Introduction to ORM
ORM
SQL
SQL
JPA Walkthrough
ccn oid placed pid price
_on
qty price
Customer Order Product
name
User
uid pass
Salesman Invoice
salary iid paid
_on
@Entity
class Customer
{
uid pass
String username;
Customer
String password;
name ccn
String full_name;
String cc_number;
boolean logged_in;
Set<Order> orders;
}
@Entity
@Entity
class Customer
{
@Id uid pass
String username;
Customer
String password;
name ccn
String full_name;
String cc_number;
@Transient
boolean logged_in;
@...
Set<Order> orders;
}
@Entity
@Entity
@Table (name = "Customers", schema = "V2")
class Customer
{
@Id uid pass
@Column (name = "cid")
String username;
@Column (nullable = false)
Customer
String password;
@Column (name = "name", nullable = false) name ccn
String full_name;
@Column (name = "ccn")
String cc_number;
@Transient
boolean logged_in;
@...
Set<Order> orders;
}
Outline
Introduction to Object Relational Mapping
Java Persistence API
Mapping Relationships
Mapping Inheritance
Entity Relationships
@OneToMany / @ManyToOne
Customer Order
@ManyToMany
Order Product
@OneToOne Order Invoice
Relationships are bidirectional
Owning side
Propagates relationship updates to the database
Usually the side with the foreign key
Owned side
Maps to the owning side
@OneToMany / @ManyToOne
class Order Customer Order
{
long order_id;
Date placed_on;
Customer customer;
Set<Product> products;
Invoice invoice;
}
@OneToMany / @ManyToOne
@Entity
class Order Customer Order
{
@Id
@GeneratedValue (strategy = GenerationType.SEQUENCE)
@Column (name = "oid")
long order_id;
@Column (nullable = false)
Date placed_on;
@...
Customer customer;
@...
Set<Product> products;
@...
Invoice invoice;
}
@OneToMany / @ManyToOne
@Entity
class Customer Customer Order
{
...
@OneToMany // owned
Set<Order> orders;
}
@Entity
class Order
{
...
@ManyToOne // owning
Customer customer;
...
}
@OneToMany / @ManyToOne
@Entity
class Customer Customer Order
{
...
@OneToMany (mappedBy = "customer", // owned
cascade = CascadeType.ALL,
fetch = FetchType.EAGER) Owned entity always
Set<Order> orders; maps to owning entity!
}
@Entity Collections are fetched
class Order lazily by default!
{
...
@ManyToOne ( // owning
optional = false)
Customer customer;
...
}
@ManyToMany
class Product Order Product
{
long prod_id;
float price;
Set<Order> orders;
}
@ManyToMany
@Entity
class Product Order Product
{
@Id
@GeneratedValue (strategy = GenerationType.SEQUENCE)
@Column (name = "pid")
long prod_id;
@Column (nullable = false)
float price;
@ManyToMany (...) // owning/owned
Set<Order> orders;
}
@ManyToMany
@Entity
class Product Order Product
{
...
@ManyToMany (mappedBy = "products", // owned
fetch = FetchType.EAGER)
Set<Order> orders;
}
@Entity
class Order
{
...
@ManyToMany (fetch = FetchType.EAGER) // owning
Set<Product> products;
...
}
@ManyToMany
@Entity
class Product Order Product
{
...
@ManyToMany (mappedBy = "products", // owned
fetch = FetchType.EAGER)
Set<Order> orders;
}
@Entity
class Order
{
...
@ManyToMany (fetch = FetchType.EAGER) // owning
@JoinTable (name = "OrderLines",
joinColumns = @JoinColumn (name = "oid"),
inverseJoinColumns = @JoinColumn (name = "pid"))
Set<Product> products;
...
}
@ManyToMany with Attributes
qty price
class OrderLine Order Product
{
pid
Order Product
qty price
Order order;
OrderLine
Product product;
int quantity;
float price;
}
@ManyToMany with Attributes
@Entity pid
class OrderLine Order Product
qty price
{
// Id?
OrderLine
@ManyToOne (optional = false) // owning
@JoinColumn (name = "oid")
Order order;
@ManyToOne (optional = false)
@JoinColumn (name = "pid")
Product product;
@Column (nullable = false)
int quantity;
@Column (nullable = false)
float price;
}
@ManyToMany with Attributes
pid
@Entity Order Product
qty price
class Order
{
... OrderLine
@OneToMany (mappedBy = "order", // owned
cascade = CascadeType.ALL)
Set<OrderLine> order_lines;
}
@Entity
class Product
{
...
@OneToMany (mappedBy = "product", // owned
cascade = CascadeType.ALL)
Set<OrderLine> order_lines;
}
@ManyToMany with Attributes
@Entity pid
class OrderLine Order Product
qty price
{
// Id?
@EmbeddedId OrderLine
OrderLineId id;
@ManyToOne (optional = false) // owning
@JoinColumn (name = "oid")
Order order;
@Embeddable
@ManyToOne (optional = false) class OrderLineId
@JoinColumn (name = "pid") {
Product product; @Column (name = "oid")
long order_id;
@Column (nullable = false)
int quantity; @Column (name = "pid")
long prod_id;
@Column (nullable = false) }
float price;
}
@OneToOne
Order Invoice
class Invoice
{
Order order;
long invoice_id;
float total;
Date paid_on;
}
@OneToOne
@Entity
class Invoice Order Invoice
{
@...
Order order;
@Id
@GeneratedValue (strategy = GenerationType.SEQUENCE)
@Column (name = "iid")
long invoice_id;
@Column (nullable = false)
float total;
Date paid_on;
}
@OneToOne
@Entity
class Invoice Order Invoice
{
@OneToOne (...) // owning
Order order;
...
}
@Entity
class Order
{
...
@OneToOne (...) // owned
Invoice invoice;
}
@OneToOne
@Entity
class Invoice Order Invoice
{
@OneToOne (optional = false) // owning
Order order;
...
}
@Entity
class Order
{
...
@OneToOne (mappedBy = "order", // owned
optional = false,
cascade = CascadeType.ALL)
Invoice invoice;
}
@OneToOne vs. @Embeddable
@Embeddable
class Invoice Order Invoice
{
@Column (name = "iid")
long invoice_id;
@Column (nullable = false) Embeddable Objects
float total;
Date paid_on; - Do not get their own table
} - Are not directly queryable
- Are deleted w/ their parent
@Entity
class Order
{
...
@Embedded
Invoice invoice;
}
Outline
Introduction to Object Relational Mapping
Java Persistence API
Mapping Relationships
Mapping Inheritance
Inheritance
ccn
Customer
name
User
uid pass
Salesman
salary
Inheritance
@Entity
@...
class User ccn
{
@Id
@Column (name = "uid")
String username; Customer
name
@Column (nullable = false)
String password;
User
@Column (nullable = false)
String full_name; uid pass
@Transient Salesman
boolean logged_in;
}
salary
Inheritance
@Entity
class Customer extends User
{ ccn
String cc_number;
}
@Entity Customer
name
class Salesman extends User
{
int salary;
} User
uid pass
Salesman
salary
Inheritance
@Entity Fields get embedded
@MappedSuperClass with subclass entities
ccn
class User
{
@Id
@Column (name = "uid") Customer
name
String username;
@Column (nullable = false)
String password; User
@Column (nullable = false) uid pass
String full_name;
Salesman
@Transient
boolean logged_in;
} salary
Customer Salesman
uid pass name ccn uid pass name salary
myahmad 1234 Yousuf 123456 tjab p@$$ Tamim
Inheritance
@Entity
| @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
| @Inheritance(strategy = InheritanceType.SINGLE) ccn
| @Inheritance(strategy = InheritanceType.JOIN)
abstract class User
{
@Id Customer
name
@Column (name = "uid")
String username;
@Column (nullable = false) User
String password;
uid pass
@Column (nullable = false)
String full_name; Salesman
@Transient
boolean logged_in; salary
}
Outline
Java Persistence API
Mapping Relationships
Mapping Inheritance
Putting it all together
Putting it all together
ccn oid placed pid price
_on
qty
Customer Order Product
name
User
Update invoice #1234
uid pass
to paid
Salesman Invoice
salary iid paid
_on
Putting it all together
// Update invoice #1234 to paid
EntityManager em = ...; // Instantiate EM
Invoice i = em.find(Invoice.class, 1234);
i.paid_on = new Date(); // defaults to "now"
em.persist(i);
Putting it all together
ccn oid placed pid price
_on
qty
Customer Order Product
name
User
Report all orders with
uid pass
unpaid invoices
Salesman Invoice
salary iid paid
_on
Putting it all together
// Report all orders with unpaid invoices
EntityManager em = ...; // Instantiate EM
List unpaidInvoices = em.createQuery(
"SELECT i FROM invoice WHERE i.paid_on IS NULL").getResultList();
for(Invoice i : unpaidInvoices) {
Order o = i.getOrder();
Customer c = o.getCustomer();
println("Customer: " + c.full_name);
println("Order #: " + String.valueOf(o.order_id));
println("Invoice #: " + String.valueOf(i.invoice_id));
float total = 0.0;
for(OrderLine ol : o.getOrderLines()) {
total += ol.price * ol.quantity;
Product p = ol.getProduct();
println("Item: " + String.valueOf(p.prod_id) + ", " +
"Qty: " + String.valueOf(ol.quantity) + ", " +
"Price: " + String.valueOf(ol.price));
}
println("Total: $" + String.valueOf(total));
println("----------------------------------");
}
Next Class
Disks and Files – Part I