Hibernate HandsOn : Saving Objects

In the previous post we created a basic hibernate project and connect it with DB. We used many defaults, like the table and columns created were the same as the class and attributes names. In most cases, we use an existing table and columns name. For now our DB table is having following structure:

employee_details
Id Name Phone Address

Lets change our DTO accordingly:


package com.hibernate.dto;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employee_details")
public class Employee {

@Id
 @Column(name = "Id")
 private int id;
 @Column(name = "Name")
 private String name;

 private Date dob;

 @Column(name = "Phone")
 private String mobile;
 @Column(name = "Address")
 private String address;

public int getId() {
 return id;
 }

public void setId(int id) {
 this.id = id;
 }

public String getName() {
 return name;
 }

public void setName(String name) {
 this.name = name;
 }

public Date getDob() {
 return dob;
 }

public void setDob(Date dob) {
 this.dob = dob;
 }

public String getAddress() {
 return address;
 }

public void setAddress(String address) {
 this.address = address;
 }

public String getMobile() {
 return mobile;
 }

public void setMobile(String mobile) {
 this.mobile = mobile;
 }

}

Note that dob is not mapped to any table in DB. Also there is no table column. When we used @Entity(name=”employee_details”), we changes the name of the entity itself i.s employee_details from Employee . Suppose we want our entity name to be same or different but use a different table, @Table is used.
Your HibernateTest class is more or less same:


package com.hibernate.test;

import java.util.Calendar;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.hibernate.dto.Employee;

public class HibernateTest {
 static SessionFactory sessionFactory;
 static Session session;

public static void main(String[] args) {
 System.out.println("HibernateTest");
 Employee user = new Employee();
 user.setId(1);
 user.setName("First User");
 user.setDob(new Date(90, 3, 1));//year - 90(+1900)
 user.setMobile("1234567890");
 user.setAddress("Address 1 ");
 sessionFactory = new Configuration().configure().buildSessionFactory();
 System.out.println("session factory created");
 try {
 session = sessionFactory.openSession();
 session.beginTransaction();
 session.save(user);
 session.getTransaction().commit();
 } catch (Exception e) {
 System.out.println("Exception occeured::" + e.getMessage());
 } finally {
 if (session != null) {
 session.clear();
 session.close();
 }
 }
 System.out.println("Hibernate test ended");
 }

}
}

Now, after running we noticed that hibernate automatically creates the new columns with the relevant column datatypes in DB. Like for Date it took TimeStamp in DB. This is correct most of the time but what if we can have control over this mapping.


@Basic

private String address;

@Basic tells hibernate to go with the default mapping. No need to have this annotation if we want hibernate to carry on with its default. @Basic does have a couple of attributes but if you don’t want it no point of adding as hibernate takes @Basic by default for class attributes.

What if I have a property in the class and I do not want hibernate to save it? We can mark the property as transient/static  property to the attributes.


private static/transient String address;

Another way is to add @Transient above address. Hibernate will not save it.

Suppose we have another field here say candidateHistory. We want to increase the size more than 255.

@Lob
private String candidateHistory;

@Lob denotes that this is a large object. Now most of the databases supports Large object, like CLOB meaning character large object or BLOB meaning binary large object. Here @Lob is above string datatype so hibernate assumes it’s a CLOB. If its above byte its assumes it’s a BLOB.

Till now the table was created again and again. We can fix that by changing hbm2ddl.auto property to ‘update‘ in hibernate.cfg.xml. However, for testing purpose it better to keep ‘create‘.

Many times business tables do have some columns that could be used as primary keys. Such columns are called ‘Natural Keys‘. Like unique email address. Sometimes we don’t have such a column and we create a new column with some unique value each time to act as primary key. Suppose our id is a surrogate key i.e its not a business requirement and we want hibernate to generate this automatically.

HibernatePrimaryKey

If we do not tell strategy , it will take Auto.
Identity= Hibernate use identity columns feature in some DB.
Sequence=Hibernate uses the sequence object from the DB.
Table= Hibernate will create a separate sequence table and use that.

Note – Make sure your Id column in DB is set to AUTO_INCREMENT in addition of being a primary key.

So far we have assumed that all the attributes in our DTO class maps to a column in DB, but what if an attribute is an object. For example, in our DTO lets have an address object instead of String. We will also have a corresponding Address class. The easiest way to tackle this is to have additional columns in our DB and treat member variables of the Address class as member variables of Employee class.

Change address attribute in our DTO:


@Embedded
private Address address; //generate getter and setters

New Address class :


@Embeddable

public class Address {

private String street;

private String city;

private String state;

private String pincode;

//getters and setters of all

}

Note: @Embeddable/@Embedded , any one can be skipped. If @Embedded not written in Employee class, Hibernate sees the embeddable class and assumes its embedded object. Similarly vice versa.

This works fine if the object in question (Address) is a value object. Value Object are those which do not have any meaning of their own. Like the address object doesn’t make sense alone, it has to be associated with User class telling whose address.

Change your HibernateTest class which not sets address in the employee object by creating a Address object. Now run the class, you will see that now 4 new columns have been added to your employee_details table in DB.

Now, how to configure the columns of an embedded object? Normal objects can be configured using @Column. One of the way is to go to the Embaddable class/object and do it there.


@Embeddable
public class Address {
 @Column(name="Street_Present")
 private String street;
 @Column(name="City_Present")
 private String city;
 @Column(name="State_Present")
 private String state;
 @Column(name="Pincode_Present")
 private String pincode;

//getters and setters

What if we have two addresses in our user class- permanentAddress and presentAddress. We can override the attributes in user class so that it doesn’t takes the default. Eg.


@Embedded
 @AttributeOverrides({
 @AttributeOverride(name = "street", column = @Column(name = "Street_Permanent")),
 @AttributeOverride(name = "city", column = @Column(name = "City_Permanent")),
 @AttributeOverride(name = "state", column = @Column(name = "State_Permanent")),
 @AttributeOverride(name = "pincode", column = @Column(name = "Pincode_Permanent")) })
 private Address permanentAddress;
 private Address presentAddress;

Now parameters setted in permanentAddress will go these columns that have been referred in AttributeOverride. presentAddress will go to the columns according to the Embeddable class Address.
Modify your HibernateTest accordingly and test. Now there will be 8 new columns for addresses.

Grab the code for this tutorial from my GitHub repository.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: