This article is not up to date and it has been substitute with new up to date content.

Please look the new up to date content.

The Data Model Mapping

by Laura Cigardi
17,866 views Published on Oct 24, 2011
Applies to: All versions
Table of contents

Introduction

WebRatio allows to create a Web application creating two models, the Data Model and the Web Model. The Data Model is an ER diagram in which there are all the information the Web application has to manage; the Web Model, instead, is a group IFML diagrams specifying the Web application pages and their content. To specify the page content the WebRatio designer must refer to objects contained in the Data Model, which represents the starting point when creating a new Web Project. In this way, it's possible to create all the Web application model without considering the Database used by the Web application. There is a high level of abstraction which allows to delay the Database choice, and to change this choice during the development. Once the Database is chosen, the information connecting each Data Model object (entity, relationship or attribute) with a Database object (table, view or column) are stored in the Mapping. A definition of the mapping can be:

"A one-to-one relationship between each element in the Data Model and its corresponding element in the Database. With the mapping, each operation which refers to the Data Model can be translated in SQL statements for the specific Database."

Consider the following table. In the first column there's the Data Model of the Acme Sample Project. In the second column there's an example of a PostreSQL database corresponding to the Data Model.

Data Model Database
top
Mapping

Synchronization

The Synchronization is the process that allows to create the Mapping. The first operation to do is to specify the Database connection properties in the Properties View.

Once the Database has been specified, it's possible to choose whether to manually define the Mapping or let WebRatio do it automatically using the Syncronization. The Synchronization consists in a comparison between what is defined in the Data Model and what is defined in the Database. WebRatio detects all the differences between the Data Model and the Database.

At this point it's possible to choose whether to export in the Database the elements defined in the Data Model or to import in the Data Model the information contained in the Database. The choice between the two operations depends on the Database status. If the Database does not exist and you are going to create it starting from the Web application, then you will choose to export all the Data Model information; instead, if there is an existing Database (e.g. Company Database) from which you are going to start developing and maybe adding new information, you will choose to import some of the Database content. The first option is called Forward Engineering, the second Reverse Engineering.

Forward Engineering

Suppose that you are developing a Web application and the Database doesn't exist and has be created from scratch. You will create all the entities, attributes and relationships in the Data Model, then you need to create all the relative elements in the Database to make the Web application work.

This is the case of the Forward Engineering. This process consists of the following steps:

  • Declare the Database in WebRatio
  • Create the Data Model of the Web application
  • If the database already contains elements (tables, relations, views, etc.) then manually define the mapping between the elements
  • If the database is empty then export all the elements of the Data Model in the Database

As an example, suppose that we add to the Data Model the new entity "Customer".

The "Synchronyze" functionality detects that this new Entity is defined in the Data Model and is not defined in the Database.

We can choose to export this new element to the Database.

This means that WebRatio automatically creates the SQL statements to create the table (the particular SQL dialect used depends on the Database type) and then we can choose to save the statements and/or execute them in the Database. The mapping between the Data Model element and the exported Database element is automatically created.

Note that the datatypes are automatically translated in datatypes supported by the Database used (in the Data Model: string, integer, in Postgres Database: Varchar (255), Int4)

Manual mapping

It's always possible to manually define the mapping for new elements in the Data Model. After the creation of a new element we can define, element by element, the mapping. This is done with the mapping properties of the element selected. For every new element (Entity, Attribute, Relation) we can choose the linked Database element from the Database Metadata (retrieved with the "Refresh" functionality).

After the creation of the "Customer" entity, the Mapping properties are empty:

For the Entity and for every attribute we manually define the mapping:

Reverse Engineering

The Reverse Engineering process is used when we want to create an application that works with an existent Database. This is the case of several application working on the same Database, or application using Databases with lots of data. It's not possible to create a new Database, we need to "import" the Database in the Data Model, and then start building the application.

The process of the Reverse Engineering consists of the following steps:

  • Declare the Database in WebRatio
  • "Import" the Database
  • Choose the keys of the "imported" entities
  • Choose the datatypes of the attributes

The primary key of the imported entity must be chosen only if the particular Database doesn't shows the primary keys. The datatypes must be chosen only if particular types are used (that WebRatio isn't able to recognize).

Suppose that in our ACME application we want to import the table "Invoice" that contains all the invoices of the shop. The "Synchronize" functionality detects a table in the Database not mapped in the Data Model.

 

After choosing to import the table into Model, we can use the "Invoice" Entity in our Datamodel.

Generated code

The generation of the Data Model results in the creation of a set of files for each Data Model object. The generated files are those needed by Hibernate(the database persistence layer) in order to correctly manage the interaction between the Web application and the chosen database. The generation process uses the Mapping information in order to create those files. For each Data Model entity the generation process produces:

  • a XML Hibernate mapping file
  • a Java class

It's possible to see the generated file browsing the


[path to the application]/WEB-INF/classes/com/webratio/webapp

folder or directly from the Web Project right-clicking on an Entity in the Data Model and choosing the "Open Generated Code" command.

Change the Java Package

Starting from WebRatio 5.1.X it's possible to change the default package in which the Java classes related to the Data Model are generated. The default ont is "com.webratio.webapp" but it's possible to customize it. To do this you just have to select the Data Model node from the Outline View and set the Java Package Name property.

Hibernate mapping

The Hibernate mapping XML files respect the Entity structure. Each file contains:

  • a "property" element for each Entity's attribute, with the "column" attribute specifiying the column connected to the attribute retrieved from the Mapping information
  • a "set" element for each N-N relationship outgoing from the Entity
  • a "many-to-one" element for each a-N relationship outgoing from the Entity

As an example, here's the code generated for the "Product" entity:


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">



<hibernate-mapping schema="APP" default-cascade="none" default-access="property" default-lazy="true" auto-import="true">

  <class schema="APP" name="com.webratio.webapp.Product" table="`PRODUCT`" dynamic-update="true" dynamic-insert="true" 

mutable="true" polymorphism="implicit" select-before-update="false" optimistic-lock="version">

    <id name="OID" column="`OID`" type="java.lang.Integer">

      <generator class="com.webratio.rtx.hibernate.MaxPlusOneIncrementGenerator"/>

    </id>

    <property name="code" column="`CODE`" type="java.lang.Integer" unique="false" optimistic-lock="true" lazy="false"

generated="never"/>

    <property name="descriptionCLOB" column="`DESCRIPTION`" type="clob" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

    <property name="description" column="`DESCRIPTION`" type="text" insert="false" update="false" unique="false" optimistic-

lock="true" lazy="false" generated="never"/>

    <property name="name" column="`NAME`" type="java.lang.String" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

    <property name="price" column="`PRICE`" type="java.lang.Double" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

    <property name="thumbnailRef" column="`THUMBNAIL`" type="java.lang.String" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

    <property name="highlighted" column="`HIGHLIGHTED`" type="java.lang.Boolean" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

    <set name="product2Combination" table="`PRODUCT_COMBINATION`" schema="APP" inverse="false" mutable="true" sort="unsorted" 

optimistic-lock="true" embed-xml="true">

      <key on-delete="noaction">

        <column name="`PRODUCTOID`"/>

      </key>

      <many-to-many class="com.webratio.webapp.Combination" not-found="exception" embed-xml="true" unique="false">

        <column name="`COMBINATIONOID`"/>

      </many-to-many>

    </set>

    <set name="product2TechRecord" table="`TECHRECORD_PRODUCT`" schema="APP" inverse="false" mutable="true" sort="unsorted" 

optimistic-lock="true" embed-xml="true">

      <key on-delete="noaction">

        <column name="`PRODUCTOID`"/>

      </key>

      <many-to-many class="com.webratio.webapp.TechRecord" not-found="exception" embed-xml="true" unique="false">

        <column name="`TECHRECORDOID`"/>

      </many-to-many>

    </set>

    <set name="product2BigImage" inverse="true" mutable="true" sort="unsorted" optimistic-lock="true" embed-xml="true">

      <key on-delete="noaction">

        <column name="`PRODUCTOID`"/>

      </key>

      <one-to-many class="com.webratio.webapp.BigImage" not-found="exception" embed-xml="true"/>

    </set>

    <many-to-one name="product2Category" class="com.webratio.webapp.Category" update="true" insert="true" not-found="exception" 

unique="false" optimistic-lock="true" embed-xml="true">

      <column name="`CATEGORYOID`"/>

    </many-to-one>

  </class>

  <class schema="APP" entity-name="Rel_Product_to_product2Combination" table="`PRODUCT_COMBINATION`" dynamic-update="true" dynamic-

insert="true" mutable="true" polymorphism="implicit" select-before-update="false" optimistic-lock="version">

    <composite-id mapped="false" unsaved-value="undefined">

      <key-property name="source_OID" column="`PRODUCTOID`" type="java.lang.Integer"/>

      <key-property name="target_OID" column="`COMBINATIONOID`" type="java.lang.Integer"/>

    </composite-id>

  </class>

  <class schema="APP" entity-name="Rel_Product_to_product2TechRecord" table="`TECHRECORD_PRODUCT`" dynamic-update="true" dynamic-

insert="true" mutable="true" polymorphism="implicit" select-before-update="false" optimistic-lock="version">

    <composite-id mapped="false" unsaved-value="undefined">

      <key-property name="source_OID" column="`PRODUCTOID`" type="java.lang.Integer"/>

      <key-property name="target_OID" column="`TECHRECORDOID`" type="java.lang.Integer"/>

    </composite-id>

  </class>

  <class schema="APP" entity-name="Rel_Product_to_product2BigImage" table="`BIGIMAGE`" dynamic-update="true" dynamic-insert="true" 

mutable="true" polymorphism="implicit" select-before-update="false" optimistic-lock="version">

    <id name="target_OID" column="`OID`" type="java.lang.Integer"/>

    <property name="source_OID" column="`PRODUCTOID`" type="java.lang.Integer" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

  </class>

  <class schema="APP" entity-name="Rel_Product_to_product2Category" table="`PRODUCT`" dynamic-update="true" dynamic-insert="true" 

mutable="true" polymorphism="implicit" select-before-update="false" optimistic-lock="version">

    <id name="source_OID" column="`OID`" type="java.lang.Integer"/>

    <property name="target_OID" column="`CATEGORYOID`" type="java.lang.Integer" unique="false" optimistic-lock="true" lazy="false" 

generated="never"/>

  </class>

</hibernate-mapping>

Java classes

The Java classes respect the Entity structure. Each class contains:

  • a variable for each Entity's attribute
  • a variable for each Entity's relationship. Depending on the relationship's cardinality the variable can be
    • a Set for N cardinality relationship roles,
    • a simple variable for 1 cardinality relationship roles
  • a getter and setter method for each variable
  • the "equals" method which allows to state when two objects of the same class are equals
  • the "toString" method
  • the "hashCode" method

As an example, here's the code generated for the "Product" entity:


package com.webratio.webapp;



public class Product implements java.io.Serializable {

    /** Serial version identifier. */

    private static final long serialVersionUID = 1L;



    private java.lang.Integer _OID;



    private java.lang.Integer _code;



    private java.lang.String _description;



    private java.sql.Clob _descriptionCLOB;



    private java.lang.String _name;



    private java.lang.Double _price;



    private java.lang.String _thumbnailRef;



    private java.lang.Object _thumbnail;



    private java.lang.Boolean _highlighted;



    private java.util.Set _product2Combination = new java.util.HashSet();



    private java.util.Set _product2TechRecord = new java.util.HashSet();



    private java.util.Set _product2BigImage = new java.util.HashSet();



    private Category _product2Category;



    private float _searchScore;



    public java.lang.Integer getOID() {

        return _OID;

    }



    public void setOID(java.lang.Integer _OID) {

        this._OID = _OID;

    }



    public java.lang.Integer getCode() {

        return _code;

    }



    public void setCode(java.lang.Integer _code) {

        this._code = _code;

    }



    public java.lang.String getDescription() {

        return _description;

    }



    public void setDescription(java.lang.String _description) {

        this._description = _description;

    }



    public java.sql.Clob getDescriptionCLOB() {

        return _descriptionCLOB;

    }



    public void setDescriptionCLOB(java.sql.Clob _descriptionCLOB) {

        this._descriptionCLOB = _descriptionCLOB;

    }



    public java.lang.String getName() {

        return _name;

    }



    public void setName(java.lang.String _name) {

        this._name = _name;

    }



    public java.lang.Double getPrice() {

        return _price;

    }



    public void setPrice(java.lang.Double _price) {

        this._price = _price;

    }



    public java.lang.String getThumbnailRef() {

        return _thumbnailRef;

    }



    public void setThumbnailRef(java.lang.String _thumbnailRef) {

        this._thumbnailRef = _thumbnailRef;

    }



    public java.lang.Object getThumbnail() {

        return _thumbnail;

    }



    public void setThumbnail(java.lang.Object _thumbnail) {

        this._thumbnail = _thumbnail;

    }



    public java.lang.Boolean getHighlighted() {

        return _highlighted;

    }



    public void setHighlighted(java.lang.Boolean _highlighted) {

        this._highlighted = _highlighted;

    }



    public java.util.Set getProduct2Combination() {

        return _product2Combination;

    }



    public void setProduct2Combination(java.util.Set _product2Combination) {

        this._product2Combination = _product2Combination;

    }



    public java.util.Set getProduct2TechRecord() {

        return _product2TechRecord;

    }



    public void setProduct2TechRecord(java.util.Set _product2TechRecord) {

        this._product2TechRecord = _product2TechRecord;

    }



    public java.util.Set getProduct2BigImage() {

        return _product2BigImage;

    }



    public void setProduct2BigImage(java.util.Set _product2BigImage) {

        this._product2BigImage = _product2BigImage;

    }



    public Category getProduct2Category() {

        return _product2Category;

    }



    public void setProduct2Category(Category _product2Category) {

        this._product2Category = _product2Category;

    }



    public float getSearchScore() {

        return _searchScore;

    }



    public void setSearchScore(float _searchScore) {

        this._searchScore = _searchScore;

    }



    public String toString() {

        java.lang.StringBuffer sb = new java.lang.StringBuffer();

        sb.append(super.toString());

        int n = sb.length() - 1;

        if (sb.charAt(n) == ']') {

            sb.setCharAt(n, ',');

        } else {

            sb.append('[');

        }

        if (_OID != null)

            sb.append("OID=" + _OID + ',');

        if (_code != null)

            sb.append("code=" + _code + ',');

        if (_description != null)

            sb.append("description=" + _description + ',');

        if (_name != null)

            sb.append("name=" + _name + ',');

        if (_price != null)

            sb.append("price=" + _price + ',');

        if (_thumbnail != null)

            sb.append("thumbnail=" + _thumbnail + ',');

        if (_highlighted != null)

            sb.append("highlighted=" + _highlighted + ',');

        n = sb.length() - 1;

        if (sb.charAt(n) == ',') {

            sb.setCharAt(n, ']');

        } else if (sb.charAt(n) == '[') {

            sb.deleteCharAt(n);

        }

        return sb.toString();

    }



    public boolean equals(java.lang.Object obj) {

        if (!(obj instanceof Product)) {

            return false;

        }

        Product otherProduct = (Product) obj;

        java.lang.Object key = null;

        java.lang.Object otherKey = null;

        key = this.getOID();

        otherKey = otherProduct.getOID();

        if (key == null) {

            if (otherKey != null) {

                return false;

            }

        } else {

            if (otherKey == null) {

                return false;

            } else if (!key.equals(otherKey)) {

                return false;

            }

        }

        return true;

    }



    public int hashCode() {

        int hashCode = 0;

        java.lang.Object key = null;

        key = this.getOID();

        if (key != null) {

            hashCode |= key.hashCode();

        }

        return hashCode;

    }

}

 

 
 

This article is not up to date and it has been substitute with new up to date content.

Please look the new up to date content.