JBoss.org Community Documentation
A dependent value class (DVC) is a fancy term used to identity any Java class that is the type of a cmp-field
other than the automatically recognized types core types such as strings and number values. By default, a DVC is serialized, and the serialized form is stored in a single database column. Although not discussed here, there are several known issues with the long-term storage of classes in serialized form.
JBoss also supports the storage of the internal data of a DVC into one or more columns. This is useful for supporting legacy JavaBeans and database structures. It is not uncommon to find a database with a highly flattened structure (e.g., a PURCHASE_ORDER
table with the fields SHIP_LINE1
, SHIP_LINE2
, SHIP_CITY
, etc. and an additional set of fields for the billing address). Other common database structures include telephone numbers with separate fields for area code, exchange, and extension, or a person's name spread across several fields. With a DVC, multiple columns can be mapped to one logical field.
JBoss requires that a DVC to be mapped must follow the JavaBeans naming specification for simple properties, and that each property to be stored in the database must have both a getter and a setter method. Furthermore, the bean must be serializable and must have a no argument constructor. A property can be any simple type, an unmapped DVC or a mapped DVC, but cannot be an EJB. A DVC mapping is specified in a dependent-value-class
element within the dependent-value-classes
element.
Here is an example of a simple ContactInfo
DVC class.
public class ContactInfo implements Serializable { /** The cell phone number. */ private PhoneNumber cell; /** The pager number. */ private PhoneNumber pager; /** The email address */ private String email; /** * Creates empty contact info. */ public ContactInfo() { } public PhoneNumber getCell() { return cell; } public void setCell(PhoneNumber cell) { this.cell = cell; } public PhoneNumber getPager() { return pager; } public void setPager(PhoneNumber pager) { this.pager = pager; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email.toLowerCase(); } // ... equals, hashCode, toString }
The contact info includes a phone number, which is represented by another DVC class.
public class PhoneNumber implements Serializable { /** The first three digits of the phone number. */ private short areaCode; /** The middle three digits of the phone number. */ private short exchange; /** The last four digits of the phone number. */ private short extension; // ... getters and setters // ... equals, hashCode, toString }
The DVC mappings for these two classes are relatively straight forward.
<dependent-value-classes> <dependent-value-class> <description>A phone number</description> <class>org.jboss.cmp2.crimeportal.PhoneNumber</class> <property> <property-name>areaCode</property-name> <column-name>area_code</column-name> </property> <property> <property-name>exchange</property-name> <column-name>exchange</column-name> </property> <property> <property-name>extension</property-name> <column-name>extension</column-name> </property> </dependent-value-class> <dependent-value-class> <description>General contact info</description> <class>org.jboss.cmp2.crimeportal.ContactInfo</class> <property> <property-name>cell</property-name> <column-name>cell</column-name> </property> <property> <property-name>pager</property-name> <column-name>pager</column-name> </property> <property> <property-name>email</property-name> <column-name>email</column-name> <jdbc-type>VARCHAR</jdbc-type> <sql-type>VARCHAR(128)</sql-type> </property> </dependent-value-class> </dependent-value-classes>
Each DVC is declared with a dependent-value-class
element. A DVC is identified by the Java class type declared in the class element. Each property to be persisted is declared with a property element. This specification is based on the cmp-field
element, so it should be self-explanatory. This restriction will also be removed in a future release. The current proposal involves storing the primary key fields in the case of a local entity and the entity handle in the case of a remote entity.
The dependent-value-classes
section defines the internal structure and default mapping of the classes. When JBoss encounters a field that has an unknown type, it searches the list of registered DVCs, and if a DVC is found, it persists this field into a set of columns, otherwise the field is stored in serialized form in a single column. JBoss does not support inheritance of DVCs; therefore, this search is only based on the declared type of the field. A DVC can be constructed from other DVCs, so when JBoss runs into a DVC, it flattens the DVC tree structure into a set of columns. If JBoss finds a DVC circuit during startup, it will throw an EJBException
. The default column name of a property is the column name of the base cmp-field
followed by an underscore and then the column name of the property. If the property is a DVC, the process is repeated. For example, a cmp-field
named info
that uses the ContactInfo
DVC would have the following columns:
info_cell_area_code info_cell_exchange info_cell_extension info_pager_area_code info_pager_exchange info_pager_extension info_email
The automatically generated column names can quickly become excessively long and awkward. The default mappings of columns can be overridden in the entity element as follows:
<jbosscmp-jdbc> <enterprise-beans> <entity> <ejb-name>GangsterEJB</ejb-name> <cmp-field> <field-name>contactInfo</field-name> <property> <property-name>cell.areaCode</property-name> <column-name>cell_area</column-name> </property> <property> <property-name>cell.exchange</property-name> <column-name>cell_exch</column-name> </property> <property> <property-name>cell.extension</property-name> <column-name>cell_ext</column-name> </property> <property> <property-name>pager.areaCode</property-name> <column-name>page_area</column-name> </property> <property> <property-name>pager.exchange</property-name> <column-name>page_exch</column-name> </property> <property> <property-name>pager.extension</property-name> <column-name>page_ext</column-name> </property> <property> <property-name>email</property-name> <column-name>email</column-name> <jdbc-type>VARCHAR</jdbc-type> <sql-type>VARCHAR(128)</sql-type> </property> </cmp-field> </entity> </enterprise-beans> </jbosscmp-jdbc>
When overriding property info for the entity, you need to refer to the property from a flat perspective as in cell.areaCode
.