Object Relational Mapping
Purpose of OJB mappings
OJB repository files map the following information:
- Which
BusinessObject
is mapped to which database table - Which getter/setter method in the BO is mapped to which database column
- 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:
- http://db.apache.org/ojb/docu/guides/repository.html#class-descriptor-N104E3
- http://db.apache.org/ojb/docu/guides/repository.html#field-descriptor-N105C6
- http://db.apache.org/ojb/docu/guides/repository.html#field-descriptor-N105C6
- http://db.apache.org/ojb/docu/guides/repository.html#collection-descriptor-N10770
- http://db.apache.org/ojb/docu/guides/repository.html#foreignkey
- http://db.apache.org/ojb/docu/guides/repository.html#inverse-foreignkey
- http://db.apache.org/ojb/docu/guides/basic-technique.html
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 representationorg.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.
<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:
- The
CA_ACCOUNT_T
table is mapped to theorg.kuali.kfs.coa.businessobject.Account
business object - 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 - 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 - The
ACCOUNT_NM
column is mapped to the "accountName" property of the BO and is a VARCHAR - The
ACCT_FSC_OFC_UID
column is mapped to the "accountFiscalOfficerSystemIdentifier" property of the BO and is a VARCHAR - The
OBJ_ID
column is mapped to the "objectId" property, is indexed, and is a VARCHAR - 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:
- It is of type
Chart
- 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)
- 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
- the auto-delete attribute is none: When the account is deleted using OJB, the chart object will not be deleted
- The reference is proxied, meaning that the database will only be queried for the
Chart
when a method is called on thechartOfAccounts
attribute - 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 theChart
BO. TheChart
BO has one primary key field, and the value from account'schartOfAccountsCode
is used as the value forChart
's first primary key value.
We can determine the following information about the "subAccounts" collection reference:
- 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. - Each element of the collection is of type
org.kuali.kfs.coa.businessobject.SubAccount
. - 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)).
- the auto-update attribute is object: When the account is inserted/updated, the sub-account collection is inserted/updated as well.
- the auto-delete attribute is object: When the account is deleted, then the corresponding sub-accounts will be deleted as well.
- 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. - The
<inverse-foreignkey>
specifies the fields of the element BO (i.e.SubAccount
) that will match the primary key fields of theAccount
BO. The first entry indicates that the "chartOfAccountsCode" attribute in theSubAccount
BO will match with the first primary key value of theAccount
BO, which happens to be named "chartOfAccountsCode" as well. The second entry indicates that the "accountNumber" attribute in theSubAccount
BO will match with the second primary key value of theAccount
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.