5.4 DataView

DataViews are used to declare multiple data centric views of your entities required for different use-case (or context) and client.

Why do we need data views?

Imagine the standard use case of an user interface with a search form, result list and detail form. If you think about this rather simple scenario and how many data representations of one and the same data concept (entity) is required you would roughly come up with the following:

One could argue that this is a maintenance nightmare and that its simpler to always reuse one superset structure containing all attributes for every use-case. Altough this approach certainly works we are thinking a little bit different about this problem because of the following lessons learned:

Therefore we think its best to have a separate structure for each use-case because

We call this structure data views because that is what they really are. A dataview definition starts with the dataview keyword followed by a name and is shown in the following example.

// dataview of entity 'Customer' including all attributes of Customer
// Note: actually you DONT have to declare such views because the default generator templates create so called default dataviews for each entity
// which look alike the following dataview definition. The name of the default view is always <<EntityName>>View  
dataview CustomerView {
    Customer.*
}

// dataview of entity 'Customer' with one 'local' attribute and two included customer attributes
dataview CustomerSearchView  {
 String sortKey
 Customer.lastName 
 Customer.birthDate
}

// dataview of entity 'Customer' which reference anothers dataview
dataview CustomerOrderView {
    Customer.lastName 
    Customer.birthDate
    Customer.invoiceAddress<AddressView> // reference mapping with explicit dataview
    Customer.billingAddress // reference mapping with the default address dataview i.e. AddressView
}

// default dataview of entity 'Address'
dataview AddressView {
    Address.*
}

Default Entity DataView

Besides the manually defined dataviews the default ModelModifier will also create an implicit DataView (we call this the default entity DataView) for each entity declaration which automatically includes all required simple typed attributes (String,Integer,..) and the to-one relations (or rather the ForeignKey to the related entity) of the entity from which the DataView gets derived. The name of this automatically created DataView is deduced from the entity and by default ends with a View suffix. (e.g. Entity Customer will automatically create a DataView named CustomerView) Nevertheless, sometimes its required to include additional attributes (besides the aforementioned) in the default DataView which can be easily achieved by means of manual declaration of a DataView with the same name as the default DataView. The existence of such a DataView within the same model file as the corresponding entity prevents the implicit creation and can be used to modify (only addition) the structure of the default DataView.

default entity dataview nameCustomerViewentity Customer {
    String firstName
    String lastName
    String ssn
    Address address
    Order[] orders
}

// the existence of a dataview with the  prevents the automatically creation of the implicit one

dataview  {
   Customer.*  // this is the default behaviour and can be omitted if the default fits your need = include all simple type attributes and all to-one entity references   
   // since orders is a many valued (collection) entity reference type its not included in the default DataView and we want to overrule this standard behaviour here 
   Customer.orders
}
 

Note: With the concept of DataViews we support the recommendation from the hibernate best practice chapter given below:

"Use the open session in view pattern, or a disciplined assembly phase to avoid problems with unfetched data: ...Unless you are prepared to hold the persistence context (the session) open across the view rendering process, you will still need an assembly phase. Think of your business methods as having a strict contract with the presentation tier about what data is available"

Mapping entity references

By default only the identity values of referenced entities are mapped in dataviews. If the real dataviews of the referenced entities should be mapped as well one has just to specifiy an additional property in the dataview definition: the property of the entities reference. Here is an example, which results in a CustomerOptionalForeignKeyTestDto class with an addtional property named optionalorder, whose name could be altered by the as keyword in the dsl, of type OrderOfCustomerView (the default dataview) instead of only having a String property holding the identity value of the referenced OptionalOrder by default:

entity Customer {
    id String oid
    version Date ^version
    String(25) firstName
        required = true
        title = "First name"
    String(25) lastName
        required = true
        title = "Last name"    
    composition OrderOfCustomer optionalOrder
    oppositeof customer  
    }
    
dataview CustomerOptionalForeignKeyTestDto {
    Customer.all
    Customer.optionalOrder
}    
    

If another dataview should be mapped to than the default dataview, for instance the OrderOfCustomerLightView, then change the definition of the dataview like in the following example:

dataview CustomerOptionalForeignKeyTestDto {
    Customer.all
    Customer.optionalOrder <OrderOfCustomerLightView>
}    

For each dataview element one java class is generated and this java class contains all the attributes and references included from the corresponding entity.

Note: There is currently no built-in support to customize this behaviour without to change the default provided workflow and templates.