Version 1

    Several people have asked why Hibernate won't allow a single subclass to be mapped across multiple tables (it is possible to map a single class hierarchy across multiple tables using <joined-subclass>). We consider it an essential element of good object model design that the object model be at least as granular as the relational model. If the original data modeller decided that certain columns should be split across two different tables, then there must have been some kind of conceptual justification for that. There is no reason not to also make that distinction in the object model. (The finer grained your object model, the more reuseable and more refactorable it is.)

     

    However, we don't necessarily wish to expose all of this fine granularity to clients. Suppose our existing relational model defines the tables CUSTOMER and CUSTOMER_HISTORY. (We will assume a primary key association between the two tables; with minor changes this model also applies to foreign key associations.) To our application we wish to expose a single Customer class. We can implement Customer as follows:

    public class Customer {
    private Long id;
    private CustomerHistory hist;
    private String name;
    ....
    public Long getId() {
    return id;
    }
    private void setId(Long id) {
    this.id=id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name=name;
    }
    private CustomerHistory getHistory() {
    return hist;
    }
    private void setHistory(CustomerHistory hist) {
    this.hist=hist;
    }
    ....
    public Calendar getFirstPurchaseDate() {
    return hist.getFirstPurchaseDate();
    }
    public void setFirstPurchaseDate(Calendar cal) {
    hist.setFirstPurchaseDate(cal);
    }
    ....
    }
    
    public class CustomerHistory {
    private Long id;
    private Calendar firstPurchaseDate;
    ....
    public Long getId() {
    return id;
    }
    private void setId(Long id) {
    this.id=id;
    }
    public Calendar getFirstPurchaseDate() {
    return firstPurchaseDate;
    }
    public void setFirstPurchaseDate(Calendar cal) {
    firstPurchaseDate = cal;
    }
    ....
    }
    

    Now our mapping could look like:

    <class name="Customer"
    table="CUSTOMER">
    
    <id name="id" type="long">
    <generator class="sequence">
    <param>CUSTOMER_SEQ</param>
    </generator>
    </id>
    <property name="name"/>
    <one-to-one name="history"
    class="CustomerHistory"
    constrained="true"/>
    .....
    </class>
    
    <class name="CustomerHistory"
    table="CUSTOMER_HISTORY"
    proxy="CustomerHistory">
    
    <id name="id" type="long">
    <generator class="assigned"/>
    </id>
    <property name="firstPurchaseDate"/>
    .....
    </class>
    

     

    None of this is surprising, I suppose. But now comes the cool part. Since we have declared the delegate class CustomerHistory as a proxy-able class, we can decide at deployment time whether the delegate is fetched eagerly (using an outerjoin) or lazily, simply by adding an outer-join attribute to the <one-to-one> mapping element.

    Eager:

    <one-to-one name="history"
    class="CustomerHistory"
    constrained="true"
    outer-join="true"/>
    

     

    Lazy:

    <one-to-one name="history"
    class="CustomerHistory"
    constrained="true"
    outer-join="false"/>
    

     

    At the cost of a reasonably small amount of extra code, we have a more granular object model and potentially more efficient data access.