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.