Pages

Mapping Components

Mapping Component

Let say user can have unique bank account details, consider the following relationship between User and BankAccount.


This aggregation is a stronger form of association. In java terms, this relationship is called composition but in object/relational model , there is no concept of composition. So it's better to keep these fields with User table.
BankDetails is a value type So it will not have identifier whereas User class is a entity type ,it must have identifier property.

Following are the User and BankDetails classes :

public class User {
private Long userId;
private String userName;
private String password;
private Date createdDate;
private Date modifieDate;
private BankDetails bankDetails;

// generate Getter and Setter method
}

public class BankDetails {  
private Long accountNo;
private String emailId;
private String dateOfBirth;

// generate Getter and Setter method

}

See the User.hbm.xml mapping metadata file :
<hibernate-mapping>

<class name="model.User" table="USER">
<id name="userId" column="USER_ID">
<generator class="increment"/>
</id>
<property name="userName" column="USER_NAME"/>
<property name="password" column="PASSWORD"/>
<property name="createdDate" column="CREATED_DATE"/>
<property name="modifiedDate" column="MODIFIED_DATE"/>

<component name="bankDetails" class="model.BankDetails">
<property name="accountNo" column="ACCOUNT_NO"/>
<property name="emailId" column="EMAIL_ID"/>
<property name="dateOfBirth" column="DATE_OF_BIRTH"/>
</component>
</class>
</hibernate-mapping>



When you try to run the following code :

public static void main(String... str) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction txn = session.beginTransaction();
User user = new User();
user.setUserName("Rahul");
user.setPassword("********");
user.setCreatedDate(new Date());
user.setModifiedDate(new Date());
BankDetails bankDetails = new BankDetails();
bankDetails.setAccountNo(23423421123083L);
bankDetails.setDateOfBirth("16-10-1987");
bankDetails.setEmailId("gavin.king2410@gmail.com");
user.setBankDetails(bankDetails);
session.saveOrUpdate(user);
txn.commit();
session.close();
HibernateUtil.shutDown();
}

it generates following hibernate comments :
Hibernate: insert into USER (USER_NAME, PASSWORD, CREATED_DATE, MODIFIED_DATE, ACCOUNT_NO, EMAIL_ID, DATE_OF_BIRTH, USER_ID) values (?, ?, ?, ?, ?, ?, ?, ?)

and User details is saved into the database with BankDetails information.















Using derived properties

Using derived properties

The value of derived properties is evaluated an expression at runtime by using formula attribute of property element in xml mapping metadata.

<property name="itemAmount" formula="20*ITEM_AMOUNT" type="double"/>

Property does not have column attribute or sub-element, it never appear in INSERT and UPDATE SQL statement. it appears only SELECT statement.
formula may refer to the column of database table, it can call SQL function and include sub-selects queries.
Note: formula is evaluated everytime when a entity instence is fetched from the underlying database (result may be outdated if property is modified).

Generated and default property values

Let properties of a class has its value that is generated by the database when a row is inserted or updated for the first time. So hibernate application needs to be refresh object that has these properties for which the database generates these values.

Hibernate provides generated attribute for property element in xml mapping metadata.
When Hibernate executes a INSERT or UPDATE SQL query that has this generated properties , it immediatly executes a SELECT SQL query to refresh the entity object that retrieved the generated values from the database.

         <property name="createdDate" column="CREATED_DATE" generated="insert" update="false" insert="false"/>  

Note: there are three attribute values for generated attribute : always, insert, never . always value is used for both INSERT and UPDATE SQL statement.


If you set the insert="false" and update="false" in the property element, than this column will never include in the INSERT and UPDATE SQL statement. the property value will treat as readOnly.


Customizing Property Access

Customizing Property Access

There are two ways to access the property , one is direct access ( through fields) and another is using getter or setter method of the property.
you can control this default property access behavior using default-access attribute in following xml mapping metadata :

<hibernate-mapping package="com" default-access="property">
- - -
</hibernate-mapping>

There are following values of this attribute. 
default-access="field|property|noop|custom.Class"

You can also control this access strategy on the property element in hibernate xml mapping with access attribute.
<property name="itemName" column="ITEM_NAME" access="property"/>

Noop value is used to map a property that doesn't exist in java persistent class. you can use it to map virtual property in HQL queries.

You can also create your own custom property access strategy by implementing org.hibernate.property.PropertyAccessor interface on a class.

class MyPropertyAccessStrategy implements PropertyAccessor {

@Override
public Getter getGetter(Class arg0, String arg1)
throws PropertyNotFoundException {
return null;
}

@Override
public Setter getSetter(Class arg0, String arg1)
throws PropertyNotFoundException {
return null;
}
}