Object Relational Mapping

Purpose of OJB mappings

OJB repository files map the following information:

  1. Which BusinessObject is mapped to which database table
  2. Which getter/setter method in the BO is mapped to which database column
  3. Which fields(s) comprise the foreign key between a business object and its reference(s)

OJB documentation

Currently, OJB is used as the underlying persistence layer. It converts database rows into java objects upon retrieval, and vice versa upon updates/deletes. This section assumes that the reader is familiar with the basic mapping constructs/principles described on these pages:

OJB field-level conversions

This section is not about field conversions in relation to the lookup framework. They are something completely different from OJB field-level conversions.

OJB provides a way to convert data before they are persisted to and retrieved from the database. This is accomplished by specifying a class that implements org.apache.ojb.broker.accesslayer.conversions.FieldConversion in the <field-descriptor> element.

The following are the more often used converters in KFS/Rice:

  • org.kuali.rice.kns.util.OjbCharBooleanConversion: since boolean flags are typically stored as "Y" or "N" (i.e. strings) in the database but represented as {{boolean}}s within business objects, this converter automatically allows converts between the string and the boolean representation
  • org.kuali.rice.kns.util.OjbKualiEncryptDecryptFieldConversion: provides seamless encryption of values when persisting, and decryption when retrieving from the database. Beware that the business object itself holds an unencrypted value, and as such, care should be taken to ensure that unencrypted sensitive data are not exposed to unauthorized parties.
Example converter declaration from a non-Account BO
<field-descriptor name="achBankAccountNbr" column="ACH_BNK_ACCT_NBR" jdbc-type="VARCHAR" conversion="org.kuali.rice.kns.util.OjbKualiEncryptDecryptFieldConversion"/>

When to use OJB vs. data dictionary relationships

OJB relationships should be used to define relationships between tables that are guaranteed to exist within the same database.

KRIM_PRNCPL_T is the table that the delivered implementation of the PersonImpl relies on. But, we wanted to facilitate overrides of this service that involved changing the data store from the database to LDAP, for example. So, user data is not guaranteed to exist in the same database. And, joins between other entities and Person are accomplished via specification of data dictionary relationships and special logic in the corresponding getters on the java object representations of the referencing tables. Data dictionary relationships are also used in addition to OJB references when creating extended attributes.

Example OJB mapping

This example contains a simplified version of KFS's account business object. 

<class-descriptor class="org.kuali.kfs.coa.businessobject.Account" table="CA_ACCOUNT_T">
    <field-descriptor name="chartOfAccountsCode" column="FIN_COA_CD" jdbc-type="VARCHAR" primarykey="true" index="true" />
    <field-descriptor name="accountNumber" column="ACCOUNT_NBR" jdbc-type="VARCHAR" primarykey="true" index="true" />
    <field-descriptor name="accountName" column="ACCOUNT_NM" jdbc-type="VARCHAR" />
    <field-descriptor name="accountFiscalOfficerSystemIdentifier" column="ACCT_FSC_OFC_UID" jdbc-type="VARCHAR" />
    <field-descriptor name="objectId" column="OBJ_ID" jdbc-type="VARCHAR" index="true" />
    <field-descriptor name="versionNumber" column="VER_NBR" jdbc-type="BIGINT" locking="true" />

    <reference-descriptor name="chartOfAccounts" class-ref="org.kuali.kfs.coa.businessobject.Chart" auto-retrieve="true" auto-update="none" auto-delete="none" proxy="true">
        <foreignkey field-ref="chartOfAccountsCode" />
    </reference-descriptor>

    <collection-descriptor name="subAccounts" element-class-ref="org.kuali.kfs.coa.businessobject.SubAccount" collection-class="org.apache.ojb.broker.util.collections.ManageableArrayList" auto-retrieve="true" auto-update="object" auto-delete="object" proxy="true">
        <orderby name="subAccountNumber" sort="ASC" />
        <inverse-foreignkey field-ref="chartOfAccountsCode" />
        <inverse-foreignkey field-ref="accountNumber" />
    </collection-descriptor>

</class-descriptor>

In this OJB mapping, we can determine the following information:

  1. The CA_ACCOUNT_T table is mapped to the org.kuali.kfs.coa.businessobject.Account business object
  2. The FIN_COA_CD column is mapped to the "chartOfAccountsCode" property of the BO (i.e. accessed using the getChartOfAccounts and setChartOfAccounts methods), is a VARCHAR, is indexed, and is one of the fields in the primary key
  3. The ACCOUNT_NBR column is mapped to the "accountNumber" property of the BO, is a VARCHAR, is indexed, and is one of the fields in the primary key
  4. The ACCOUNT_NM column is mapped to the "accountName" property of the BO and is a VARCHAR
  5. The ACCT_FSC_OFC_UID column is mapped to the "accountFiscalOfficerSystemIdentifier" property of the BO and is a VARCHAR
  6. The OBJ_ID column is mapped to the "objectId" property, is indexed, and is a VARCHAR
  7. The VER_NBR column is mapped to the "verionNumber" property, is a BIGINT, and is used for locking

We can determine the following information about the "chartOfAccounts" reference object:

  1. It is of type Chart
  2. the auto-retrieve attribute is true: When the account is retrieved from OJB, the chart object will behave like it was retrieved as well (the proxy setting determines whether it is really retrieved when the account is retrieved)
  3. the auto-update attribute is none: When the account is updated using OJB, the chart object will not be updated even if changes have been made to it
  4. the auto-delete attribute is none: When the account is deleted using OJB, the chart object will not be deleted
  5. The reference is proxied, meaning that the database will only be queried for the Chart when a method is called on the chartOfAccounts attribute
  6. The <foreignkey> tag specifies the fields in the account BO that are in a foreign key relationship and their order with the primary key fields in the Chart BO. The Chart BO has one primary key field, and the value from account's chartOfAccountsCode is used as the value for Chart's first primary key value.

We can determine the following information about the "subAccounts" collection reference:

  1. The collection itself is of type org.apache.ojb.broker.util.collections.ManageableArrayList, which keeps track of which elements have been removed from the array, to help when deleting elements.
  2. Each element of the collection is of type org.kuali.kfs.coa.businessobject.SubAccount.
  3. the auto-retrieve attribute is true: when the account is retrieved from the database, the collection will be populated or behave as if if it were populated upon accessing the collection. (the proxy setting determines whether the database is queried when the account is retrieved from the DB or whether it will retrieve from the DB only when the collection is accessed (i.e. lazy loading)).
  4. the auto-update attribute is object: When the account is inserted/updated, the sub-account collection is inserted/updated as well.
  5. the auto-delete attribute is object: When the account is deleted, then the corresponding sub-accounts will be deleted as well.
  6. The <orderby> tag specifies the sort order of elements in the collection. In this case, the sub-account numbers will be in ascending order in the collection.
  7. The <inverse-foreignkey> specifies the fields of the element BO (i.e. SubAccount) that will match the primary key fields of the Account BO. The first entry indicates that the "chartOfAccountsCode" attribute in the SubAccount BO will match with the first primary key value of the Account BO, which happens to be named "chartOfAccountsCode" as well. The second entry indicates that the "accountNumber" attribute in the SubAccount BO will match with the second primary key value of the Account BO, which happens to be named "accountNumber" as well.

 

 

Kuali documentation is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. 

Kuali software is licensed for use pursuant to the Affero General Public License, version 3.

 Copyright © 2014 Kuali, Inc. All rights reserved. 

Portions of Kuali are copyrighted by other parties as described in the Acknowledgments screen. 

Kuali ® is a registered trademark of the Trustees of Indiana University.