how hibernate3 makes complex things easy - hibernate

26
The Professional Open Source™ Company How Hibernate3 makes (some) complex things easy Gavin King JBoss, Inc [email protected] [email protected]

Upload: lamtu

Post on 13-Feb-2017

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

How Hibernate3 makes (some) complex things easy

Gavin KingJBoss, [email protected]@jboss.com

Page 2: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Road Map

• The problems• The model• Using union-subclass mappings• A typed association• Using filters• Producing XML

Page 3: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

The problems

• Hibernate 2.1 assumes that the data model is “nice”Relationships have foreign key constraintsForeign keys point to primary keysA null association has a null foreign key (except for one-to-one special case)

• ORM solutions assume that the model is essentially staticThe data changes over time, but……at any particular time, all users see the same data

• If either of these assumptions fails, you can’t use an association mapping

You’ll need to use a query (HQL, or possibly SQL) to discover the relationships in your data

• This is a pain forMany legacy databases Databases with historical, regional, permissioned data

Page 4: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

The model

• A hypothetical legacy insurance application• Parties to a contract (policy holders, others)

are people or organizations• Addresses have a “role” (mailing, business,

home)

Identity

Person Organization

Address

mailing

business

home

1

1

1

Page 5: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

The model

• There are various standard policy definitions which change over time

• The terms of a contract (a policy variation) may also be varied over time

Identity Party PolicyVariation PolicyDefinition1 1 1** *

Page 6: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Union-subclass mappings

• What if there is no Identity table?

• We have a one-to-one association between the Party and Identity classes

But it has no foreign key constraint

• In Hibernate3, use a <union-subclass>mapping

Page 7: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Union-subclass mapping

<class name="Identity" abstract="true"><id name="id">

…</id><property name="phoneNumber"

length="20"/>

<union-subclass name="Person"><component name="name">

…</component>…

</union-subclass>

<union-subclass name="Organization"><property name="name"/>

</union-subclass>

</class>

Page 8: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Union-subclass mapping

• Queries against this class result in a SQL union

session.createQuery(“from Party p left join fetch p.identity”).list();

select …

from Party p

left join (select … from Person union select … from Organization) i

on p.id = i.id

Page 9: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Typed association

• There are three optional associations from the Identity hierarchy to the Address class

• But in the database, this is represented as the Address table having a foreign key value of the Organization or Person table, together with a “type”

• So, in the data model, we have a one-to-many association, while in the object model, we have three optional one-to-one associations

Page 10: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Typed association

public class Address implements java.io.Serializable {

public enum AddressType { MAILING, HOME, BUSINESS }

private Identity addressee;private AddressType type;private String address;private String state;private String postCode;private String country;

…}

create table Address (identityId bigint not null,addressType varchar(10) not null

check addressType in (‘MAILING’, ‘BUSINESS’, ‘HOME),street varchar(100) not null,city varchar(30) not null,…primary key (identityId, addressType)

)

Page 11: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Typed association

<class name="Address"><composite-id>

<key-many-to-one name="addressee"/><key-property name="type"

type="address_type"><column name="addressType"

check="addressType in ('HOME', 'BUSINESS', 'MAILING')"/></key-property>

</composite-id><property name=“street" length=“100"/><property name=“city" length="30"/>…

</class>

<typedef name="address_type" class="org.hibernate.demo.EnumUserType"><param name="enum">org.hibernate.demo.Address$AddressType</param>

</typedef>

Page 12: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Typed association

<class name="Identity" abstract="true"><id name="id">…</id><property name="phoneNumber"

length="20"/><one-to-one name="mailingAddress"

cascade="all"><formula>id</formula><formula>'MAILING'</formula>

</one-to-one>

<union-subclass name="Organization"><property name="name"/><one-to-one name="businessAddress"

cascade="all"><formula>id</formula><formula>'BUSINESS'</formula>

</one-to-one></union-subclass>

Page 13: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Typed association

• Queries against this class result in a SQL union

String hql =

“from Person p join fetch p.mailingAddress join fetch p.homeAddress”;

session.createQuery(hql).list();

select …

from Person p

join Address ma

on p.id = ma.identity_id and ‘MAILING’ = ma.addressType

join Address ha

on p.id = ha.identity_id and ‘HOME’ = ha.addressType

Page 14: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• A PolicyDefinition is identified by policy name and revision number

• For audit purposes, we keep the creation date of the revision

<class name="PolicyDefinition"><composite-id>

<key-property name="policyName"/><key-property name="revision"/>

</composite-id><property name="description"/><property name="creationDate"

type="calendar_date"/>…

</class>

Page 15: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• A PolicyVariation is identified by its PolicyDefinition, together with a “variation id”

• A PolicyVariation has an effectivity range

• We also track creation time, for audit purposes

Page 16: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

<class name="PolicyVariation"><composite-id>

<key-many-to-one name="definition"><column name="policyName"/><column name="policyRevision"/>

</key-many-to-one><key-property name="variationId"/>

</composite-id><property name="creationDate"

type="calendar_date"/><property name="effectiveStartDate"

type="calendar_date"/><property name="effectiveEndDate"

type="calendar_date"/><property name="reason"/>…

</class>

Page 17: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• A Party inherits the pk of its Identity

• It also has a creation date and region

<class name="Party"><composite-id>

<key-many-to-one name="identity" column=“id"/>

</composite-id><property name="creationDate"

type="calendar_date"/><property name="region"/>…

</class>

Page 18: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• There is a many-to-many association between Party and PolicyVariation

<set name="parties" inverse="true" table="PartyPolicyVariation">

<key><column name="policyName"/><column name="policyRevision"/><column name="variationId"/>

</key><many-to-many column="party"

class="Party"/></set>

Page 19: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• And a one-to-many association between PolicyDefinition and PolicyVariation

<set name=“variations" inverse="true"><key>

<column name="policyName"/><column name="policyRevision"/>

</key><one-to-many class="PolicyVariation"/>

</set>

Page 20: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• For a particular user, we want to filter this data model fragment by

The user’s regionOptionally, the audit dateOptionally, by effectivity

<filter-def name="AuditDate"><filter-param name="date" type="date"/>creationDate &lt; :date

</filter-def>

<filter-def name="EffectiveDate"><filter-param name="date" type="date"/>(:date between effectiveStartDate and effectiveEndDate)

</filter-def>

<filter-def name="Region"><filter-param name="region" type="string"/>region = :region

</filter-def>

Page 21: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• Now, apply these filters to our class mappings

<class name="Party">…<filter name="AuditDate"/><filter name="Region”/>

</class>

<class name="PolicyVariation">…<filter name="AuditDate"/><filter name="EffectiveDate"/>

</class>

<class name="PolicyVariation">…<filter name="AuditDate"/>

</class>

Page 22: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• Also, apply to the collection-valued associations

<set name="parties" inverse="true" table="PartyPolicyVariation">

<key>…</key><many-to-many column="party" class="Party">

<filter name="AuditDate"/>

<filter name=“Region"/></many-to-many>

</set>

<set name="variations" inverse="true"><key>…</key><one-to-many class="PolicyVariation"/><filter name="AuditDate"/><filter name="EffectiveDate"/>

</set>

Page 23: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Using filters

• Let’s actually use a filter!

session.enableFilter(“Region”).setParameter( “region”, user.getRegion() );session.enableFilter(“EffectiveDate”).setParameter( “date”, date );session.enableFilter(“AuditDate”).setParameter( “date”, date );

session.createQuery(“from PolicyVariation pv join fetch pv.parties”).list();

from PolicyVariation pvjoin PartyPolicyVariation ppv

on pv.policyName = ppv.policyNameand pv.policyRevision = ppv.policyRevisionand pv.variationId = ppv.variationId

join Party pon p.id = ppv.partyand p.region = ?and p.creationDate < ?

where (? between pv.effectiveStartDate and pv.effectiveEndDate)and pv.creationDate < ?

Page 24: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Mapping to XML

<class name="PolicyVariation“ entity-name="PolicyVariation“node=“policy-variation”>

<composite-id><key-many-to-one name="definition“ node=“definition”

embed-xml=“false”><column name="policyName"/><column name="policyRevision"/>

</key-many-to-one><key-property name="variationId“ node=“@variation-id”/>

</composite-id><property name="creationDate" node=“creation-date” type="calendar_date"/><property name="effectiveStartDate" node=“effective-start-date”

type="calendar_date"/><property name="effectiveEndDate" node=“effective-start-date”

type="calendar_date"/><property name="reason"/><set name="parties" inverse="true“ node=“.”

table="PartyPolicyVariation"><key>

<column name="policyName"/><column name="policyRevision"/><column name="variationId"/>

</key><many-to-many column="party" node=“party/@id”

class="Party“ embed-xml=“false”/></set>

</class>

Page 25: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Retrieving XML

Session dom4j = session.getSession(EntityMode.DOM4J);Element pv = (Element) dom4j.createCriteria(“PolicyVariation”)

.add( Property.forName(“definition.name”).eq(policyName) )

.add( Property.forName(“definition.revision”).eq(policyRevision) )

.add( Property.forName(“variationId”).eq(variationId) )

.uniqueResult();print(pv);

<policy-variation variation-id=“1234”><definition>

<name>Standard Contents</name><revision>3</revision>

</definition><creation-date>2003-2-4</creation-date><effective-start-date>2003-2-4</effective-start-date><party id=“123455”/><party id=“788111”/>

</policy-variation>

Page 26: How Hibernate3 makes complex things easy - Hibernate

The Professional Open Source™ Company

Further information

• http://hibernate.org