Monday, July 28, 2014

Mapping Properties in Hibernate

In this section we will look into how to map the different types of properties. All properties if mapped with annotation are by default persistent. This is different from when XML is used for mapping. In XML mapping, only the properties explicitly mapped are persistent.
Transient
If a property needs to be stopped from being persistent.
@Transient

    public int getActive() {

        return active;

    }
Now this property does not becomes part of persistent mechanism. The property resides only in the Java layer.
Temporal
Allow to map java.util.Date and java.util.Calender. In SQL the date are differentiated by whether it's a date, time or a timestamp. Timestamp has both date and time. However in Java the date is always a timestamp. It has all the information. So we have to deal with this mismatch also.
//Options for TemporalType

 //   - DATE

 //   - TIME

 //   - TIMESTAMP
@Temporal(TemporalType.TIMESTAMP)
    public Date getBirthDate() {
        return birthDate;
    }

Large Data
Large data is characterized by whether it is a binary large data (BLOB) or character larger date (CLOB)
  • Blob - byte[], Byte[]
  • Clob - char[], Character[]
BLOB and CLOB both are mapped with Lob annotation
@Lob

public byte[] getPicture() {

        return picture;

}
Enumeration
Enumeration are type safe way of restricting the choice in Java. Let's say we have enum defined in Java as
public enum StudentType {

    CURRENT,

    ALUMNI

}
to specify the usage of this enum in entity
@Enumerated(EnumType.STRING)

public StudentType getStudentType() {

        return studentType;

    }    
Enum Type can be String or Ordinal. If String is specified, in the database CURRENT or ALUMNI is stored. If ordinal is specified 0 or 1 is saved. If Enum Type is omitted ORDINAL is taken as default.
Derived Properties
Derived properties are useful to calculate formulas or derived values which is not stored in database but important for business purpose.
@org.hibernate.annotations.Formula("(MARKS/TOTAL_MARKS)*100")

    public Long getPercentage() {

        return percentage

    }
The value is evaluated while fetching the entity so it might be outdated at other times. It's the responsibility of the developer to keep it updated.The property appears in the SELECT statement only and does not participates in INSERT or UPDATE statement.Even SQL expression can be passed to the underlying database so there is a chance to build database dependency.SQL functions including SQL subselects can be used.
Handling Generated Values
In DDL we define defaults to many values like SYSDATE for timestamp which means if we do not give value from Java it is automatically generated.After saving if we want to refresh the object in Java layer, we will have to call a refresh on the object. The other way is that we can tell Hibernate to refresh the value automatically after an insertion. Make sure that you have dynamicInsert set to false otherwise null value will be inserted into the database.
    @Column(updatable= false, insertable = false)

    @org.hibernate.annotations.Generated

                  (org.hibernate.annotations.GenerationTime.INSERT)

    public Double getPendingAmount() {
        return pendingAmount;
    }

Embedded classes
Embedded classes are useful for bringing fine domain modeling. We have one table but more classes mapped to it to bring rich domain model. Though Student table contains all the details for Student and his address, we will map it to two classes.
Student Table
 Student_Id

 Name

 City

 Country
Let's have city and country mapped to a different class Address. We put Embeddable annotation on it to tell that it will be used as an embedded property in an entity class
@Embeddable

public class Address {    

    protected String city;

    protected String country;
    
    @Column(name = "ADD_CITY")
    public String getCity() {

In the Student class
private Address address;

@Embedded

public Address getAddress() {

      return address;
 }
//Setter method

By default this will mapped to ADD_CITY column name as mapped in Address. To get it mapped to CITY column as in Student table, we ill have to override the column name.

   

   @Embedded

   @AttributeOverride (name= "city",column = @Column(name="CITY"))
    public Address getAddress() {
        return address;
    }

Now in this case we can navigate to Address object by holding a reference of Student object. But it's not possible to navigate from Address object to Student object. To build the bi directional navigation in Address entity

In Address class


    @org.hibernate.annotations.Parent
    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {

        this.student = student;

    }  


No comments:

Post a Comment