You are on page 1of 111

Hibernate Tutorial

javabrains.koushik.org
What is ORM tool
• object relation mapping maps the gap between
object and relational database, which why it is
called object relational mapping
• used in database layer
• implements JPA (Java Persistence Api)
•  Hibernate uses annotations which are
imported from javax.persistence.*
• class corresponds to a table and object
corresponds to row
Pain points in Hibernate

• mapping member variables to column


• mapping relationship
• handling datatype conversion e.g. boolean to
char
• Managing changes to object state i.e. update
to object and hence into db
Setting up Hibernate
• Create a java project
• Project>Projerties>Java Build Path>Liberaries>Add Library>User Library>Next>New>Give a
name and do not select system check box>Add jars>
• Add the jar for Hibernate
• Hibernate3.jar
• Add the mandatory dependencies of hibernate
• jpa.jar
• javaassist.jar
• Click ok>
• Select the check mark for the user library created.
• click finish
•  
• Installing the database
• Add the Jar for the Database
• Hiberate internally uses jdbc to connect to the database
• You would need jdbc driver to connect to db
• download the type 4 driver
• Project>Properties>Java Build Path>Libraries>Add external jar > add the jar for db
Saving without hibernate / Using JDBC for doing the save

• JDBC database configuration (IP, Port number etc)


• Model Object (We need to write a class)
• Service method to create model object(We need
to have a method that instantiates this object)
• Database design – need table and create columns
which holds the object
• DAO method to save the object using SQL queries
Saving Using Hibernate

• JDBC Database Configuration - Hibernate configuration


this is mentioned in Hibernate configuration file which gives info it needs to connect to DB
• The model object - Annotations
The model object needs to be written and we will configure hibernate to get data from this model
object using annotations.

• Service method to create the model object - Use the hibernate API
The service method will have an instance of model object (and normally it will pass the model
object to a data layer which uses jdbc). Instead in hibernate the service method would pass the
object to the hibernate API. The method would use the hibernate API directly or pass it on to data
layer which uses the hibernate API. So it’s the hibernate API which does the save of the save of
model object.

• Database design - is not needed.


You don’t really have to create the tables for every object. As long as you configure object the right
way. Hibernate creates the tables itself.
• DAO method to save the object using SQL queries - not needed.
Creating the data layer where you map the object to queries. Writing data layer code for converting
object into relational model. This is major step is not needed when you use hibernate. The service
method directly calls the hibernate API and hibernate API take care of saving the object. You don’t
have to write DAO method where we take the object, pull it apart write SQL queries not needed.
Step1: Configuring the Hibernate XML(hibernate.cfg.xml)

• Right click on project>New>File>Give the name hibernate.cfg.xml> save it in src folder>finish


• Type all the details for database
• Copy the configuration file. Make sure have db connection setting, db connection pool etc.
• <session-factory>
• <! -- Database connection settings -- >
• <property name=”connection.driver_class”>org.h2.Driver</property>
• <property name=”connection.url”>jdbc:h2:mem:db1; DB_CLOSE_DELAY=-1; </property>
• <property name=”connection.username”>sa</property>
• <property name=”connection.password”></property>
Get the DB class from the driver
Get the connection url. Create a db for connection url
userid - mentioned while installing the db
password - mentioned while installing the db
• <! -- JDBC Connection Pool (Use the built in ) -- >
• <property name=”connection.pool_size”>1</property>
• <! -- SQL Dialect -- >
• <property name=”dialect”>org.hibernate.Dialect.H2Dialect</property>
JDBC Dialect is a configuration you specify what kind of SQL dialect which hibernate is using to talk to a database.
• <! - - Disable the second level cache -- >
• <property name=”cache.provider_class”>org.hibernate.provider.NoCacheProvider</property>
• <! - - Echo all SQL to stdout -- >
• <property name=”show_sql”>true</property>
Note: hibernate will print out all the SQL which it will generate
• <! - - Drop and recreate the database schema on startup -- >
• <property name=”hbm2ddl.auto”>update</property>
hbm2ddl.auto = create
Depending on what we configure as model object it will create the DB schema to save the object.
• <! – Name the annotated entity class -- >
• <mapping class="org.javabrains.kaushik.dto.UserDetails" />
</session-factory>
hbm2ddl configurations and name annotations
• SQLDialect –
<property name=”dialect”>org.hibernate.dialect.H2Dialect</property>
• For H2 DB its H2Dialect
Dialect is a setting that depends on db
Dialect is a setting that you specify so that hibernate knows what kind of language you use to talk to a DB.
This is a class inside the hibernate package
Search for org.hibernate.package > select the dialect in the package > replace the name in the <property name=dialect>

• <property name="show_sql">true</property>
this will print out all the sql which hibernate generates

• <property name="hbm2ddl.auto">create</property>
• Create means that hibernate is goinf to drop and recreate the schema when it runs for the first time.
• <property name="hbm2ddl.auto">update</property>
• You want to retain the data that was created in the previous run then use update

Depending what we configure as model object it will create a DB schema that is required to save the model object.
If we pass an object and we ask hibernate to save the object if table is not available then hibernate will create the tables with all the
right columns to save all the member variables of the objects.
By leaving as create we don’t have to create the tables ourselves
<property name="show_sql">true</property>
• This setting prints out the SQl query in the console

• <! – Name the annotated entity class -- >


<mapping class="org.hibernate.tutorial.annotations.Event" />
We need to list out all the model classes we have configured.
</session-factory>
Annotations
@Entity - it is telling hibernate to treat this class
as Entity class. It needs to be on top of the
class name.
@Id - it needs to be on top of member variable
which you need to specify as primary key
@Column (USER_NAME) – this annotation is
placed on top of the field for UserDetailsand I
can configure each and every column I want
Step2: Write the model class

> src> new > class> Give package name - org.javabrains.kaushik.dto > class name - UserDetails > finish
package org.javabrains.kaushik.dto;
import javax.persistence.Entity
import javax.persistence.Id
 
@Entity
public class UserDetails{
@Id
private int userId
private String name
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
 public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
 
}
 
Go to configration file and specify the model class in the tag
<mapping class="org.javabrains.kaushik.dto.UserDetails" />
Creating a class that instantiates the objects of the UserDetails class

package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session

public class HibernateTest{

public static void main(String args){


UserDetails user = new UserDetails();
user.setUserID(1);
user.setUserName("First User");
 
//need to save this object in DB. We do this using the hibernate API
 
//normaly if this were a service method we create a data layer method (DAO) and pass this object to the DAO, the DAO will take care of
using hibernate API to save this. Here we use the hibernate API in service method itself.
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
 
//use sessison object to save model object. New trasaction is created and in this traction I can Save as many objects I want and I use this
transaction to define a single unit of work. I can group all these objects to be saved and can save them all inside this transaction.
session.save(user); //object is saved
sesion.getTransation.commit(); //end the tansaction by getting the transaction and doing a commit
}
}
Steps involved in using the hibernate API

• 1. Create a session factory


• 2. Create a session from the session factory
• 3. Use the session to save model objects

• The session factory is only one object per application.


It creates sessions depending on how many session
you want in your application throughout its
application period. This session factory is created out
of the configuration that we have already done. Using
the hibernate.cfg.xml we create a session factory. If
you want to save something you get a session from
the session factory and use the session to save.
Dealing with restriction on table and field name
• Now we will make some changes in the UserDetails.java file
• first default table name is the same as class name
• Some thing might not be restricted as class name but its restricted as table name
• Same goes for field names and columns

• To overcome this use


• @Entity (name="USER_DETAILS")
• If you pass the above name property then hibernate will not take the class name
under its consideration when its creating a table. Instead it will create a table out
of the name property mentioned in the @Entity

• Similarly if you mentioned @Column (USER_NAME) above the userName


property to tell hibernate dont use userName. Instead the column name should
be USER_NAME
• Also you can place the annotations on top of the field in which case it picks up
the values from the field or you can place the annotation on top of the getter in
which case it picks up the value from the getter
Positioning annotations on top of the field names
• package org.javabrains.koushik.dto;
• import javax.persistence.Entity;
• import javax.persistence.Id;
• import javax.persistence.Column
• @Entity (name="USER_DETAILS") //this creates a table with name USER_DETAILS
• public class UserDetails{
• @Id
• @Column(name=“user_id”)
• private int userId // there are acouple of annotationswhich are operating on user_id
• @Column (name="USER_NAME")
• private String userName
• public int getUserId(){
•  
• return userId
• }
•  
• public void setUserId(int userId){
• this.userId = userId;
• }
•  
• public String getUserName(){
• return userName;
• }
• public void setUserName(String userName){
• this.userName=userName;
• }
• }
• }
Positioning annotations on top of the getter method
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column
@Entity (name="USER_DETAILS") //this creates a table with name USER_DETAILS

public class UserDetails{


private int userId
private String userName
@Id
@Column(name=“user_id”)
public int getUserId(){
return userId
}
public void setUserId(int userId){
this.userId = userId;
}
@Column (name="USER_NAME")
public String getUserName(){
return userName;
}
public void setUserName(String userName){
this.userName=userName;
}
}
}
Object type to database type conversion in
hibernate
• String –converted to varchar
• date – converted to timestamp
• int – converted to int
More Annotations
• We have a model class with entity and ID annotation
• @Table (name=”USER_DETAILS”) //when you want the table to have different name
whereas the entity has the same name as the class name
• @Basic – treat it as a field which should be persisted and create a column for the class.
There are a couple of properties i.e. fetch, optional which can be used with @Basic
• @Transient - If you have a transient or static property in your class then hibernate would
not automatically persist it. It does not make sense to have a column for the user table
bec every value for the username will be same. If you don’t want the user name to be
saved in the DB just mark the string as static or transient.
• @Temporal (TemporalType.Date) / / saves only the Date and will not save the timestamp
@Temporal (TemporalType.Time)// saves only the time
• @Lob - This is used when I have a huge amount of text or byte stream and I need to tell
hibernate to choose the corresponding datatype in db so that we are not restricted to the
255 char limit that we would have upon choosing the String. If @Lob is on top of String
then hibernate assumes that it’s a clob. If its on top of a byte array then hibernate
chooses a blob.
LOB – large object; Clob – char large object; Blob – byte large object
More Annotations

• @Entity
• @Table (name=”USER_DETAILS”)
• public class UserDetails{
• @Id
• private int userId
@Transient
private String userName
@Basic
• private String address;
@Lob
• private String description;
@Temporal (TemporalType.Date)
• private Date joinedDate;

• //generate the getters and setters


•  }
•  }
Initializing the values in the main method

package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserID(1);
user.setUserName("First User");
user.setAddress(“First User’s Address”);
user.setJoinedDate(new Date());
user.setDescription()”Description of user goes here”;
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit(); //end the tansaction by getting the transaction and doing a commit
}
}
Retrieving objects using session.get

• specify the name of the class whose object


you want to retrieve along with the primary
key of the used in the model object.
Session.get() is a return type of Object in
order to put that object into my model it has
be casted by specifying the Class name. Thus
select is caused by the get method
Retrieving objects using session.get
package org.koushik.hibernate
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserID(1);
user.setUserName("First User");
user.setAddress(“First user’s address”);
user.setJoinedDate(new Date());
user.setDescription(“Description of the user goes here”);
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
user= null;
session = sessionFactory.openSession();
session.beginTransaction();
user = (UserDetails)session.get(UserDetails.class,1);
System.out.println(“User name retrieved is”+user.getUserName());
}
}
Primary Keys
• Primary Keys and different ways that hibernate provide support for primary keys.

• @Id – it created a primary key column for this userId and then it denoted it as primary key.
Then you can use this primary key for fetching data. We can pass the values of primary key
to session.get and then we can get the object itself.
• @Id @GeneratedValue – is used while specifying a surrogate key which is a type of primary
key.
• @Id @GeneratedValue(strategy=GenerationType.AUTO)
• @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
• @Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
• @Id @GeneratedValue(strategy=GenerationType.TABLES)
Primary Keys

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id
 private int userId
private String userName
 
//generate getters and setters 
}
 
}
Primary Key
package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session

public class HibernateTest{


public static void main(String args){
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("First User");
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
sesion.getTransation.commit();
session.close();
Two types of primary key - Natural key vs Surrogate key

• Natural Key - Suppose in your application you have a column which has distinct
values and which you know is mandatory. Suppose you have a registration
application, you have people registering by giving email address, first name, last
name. Suppose your business rule dictates that every user needs to have an email
ID. Every user has to provide a distinct unique email id when they are registering.
In that case we can have the email address as a primary key. Such columns which
actually are there for a business reason but then you can assign one of them as a
primary key. Such keys and are called natural keys.
• Surrogate key
• You don’t know if any column can be marked as unique. You don’t have a column
that can be marked as unique or you anticipate that could change in future. Thus
you add a new column and the purpose of the column is to entirely act as a primary
key alone it does not have any business significance but you need to have a
separate column just for it to act as a key. In that case thats called a surrogate key.
It kind of having a SNO column column in front of your table. It does not server
any other purpose and it does not carry any data apart from the fact that it marking
out all the different rows as separate and its having a unique number for each.
Managing Natural Key
• Let’s look at how hibernate supports each
• The key that we are user here is userId. If userId is
specifically for the purpose of declaring a primary key and
it does not have a business use then it’s a surrogate key.
But if it has a business use and you know it’s a loginId for
e.g. and you are making loginid as primary key then that
would be a natural key because loginId is used for other
purpose
• If we are having a natural key it would make sense for us to
provide the value because it’s of business significance, we
need to know what the value is and we need to control it.
Managing Surrogate Key
• But, if it is a surrogate key then we can ask hibernate to do the job for us. It really does not matter what
the value will be. It can be last value+1, we need to make sure that it is unique, it has to be mandatory
and cannot be optional and cannot be null. These two things are something that hibernate can manage
for us. We can tell hibernate to generate a surrogate key for us. whenever we are using such a
surrogate key e.g. this userid happens to be a surrogate key (I have added this value here I but don’t
need it for any other reason apart from using it as an id). In that case we can ask hibernate to generate
this value for us every time we do an insert. I don’t have to create this id every time, I don’t have to
pass it to hibernate. Hibernate can automatically generate and manage the newly created object keys.
• No need to specify the userid: f I have to insert a new user then I have to set the username and
hibernate will take care of creating the right userid for me.
• If I have to supply the surrogate key myself, I have to look up what is the last surrogate key id that was
created. If there were 500 users and the last userid was inserted was 500 then I would add one to it and
then insert userid 501. So this is something that I don’t have to do if I use Hibernate’s help. Hibernate
will do that work and it will generate a primary key for me. I can use that functionality of hibernate by
specifying another annotation called @GeneratedValue
• @GeneratedValue – its asking hibernate to generate this value for me. I am not going to generate this
myself. Hibernate will look at the data type of this property which is an integer and it will generate an
integer for me and then it going to add that value. So I don’t have to pass the userid value like
user.setUserId(1) , I will only pass the user name and when I do a save its going to save the value.
• Its done a nextval(hibernate_sequence). Whats happening is Hibernate is maintain a sequence
internally and generating the userid depending on sequence. Hibernate gets the next value from
sequence and uses that value (which is userid) to insert userid.
@Id @GeneratedValue(strategy=GenerationType.AUTO)

• @Id @GeneratedValue(strategy=GenerationType.AUTO)
• AUTO – means that we will let hibernate make a decision as to what strategy to use
in order to come up with unique primary keys
• IDENTITY – hibernate will use identity columns. Identity columns is a feature in some
of the database . Its not a generic feature in all the databases. SQLserver and mysql
provideidentity col feature. If you are using those databases you can say
GenerationType.IDENTITY in which case hibernate is going to use that feature of DB
in order to come up with unique primary keys.
• SEQUENCE –uses the sequence object in the DB order to come up with unique key.
which is what is happeing here Its using a hibernate sequence object. SEQUENCE
object is something that you can have in the database in order to maintain
sequences. You can use that you can add sequence, when you say nexyval it
automatically pulls up the next value and updates the sequence, so that subsequent
nextvals pull up the next data. It something that databases manage by themselves.
You can use sequence to come up with unique values for primary key.
• TABLES – you can have a separate table and that table which will have a record of the
last used primary key so that you can increment it and get the next value. If you use
this table option Hibernate will use the table for generating the primary key
@GeneratedValue – for surrogate key
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
 
@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue
private int userId
private String userName
 
//generate getters and setters
 
}
 
}
Demonstrating surrogate key usage
package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
UserDetails user2 = new UserDetails();
User2.setUserName("Second User");
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(user2);
sesion.getTransation.commit();
session.close();
Value Types and Embedding Objects

• @Embeddable - Inorder to mark a class as a


value type and tell hibernate not to create a
separate table for this I need to use
@Embeddable. @Embeddable which tells
hibernate that this object needs to be
embeddable inside something else
• Add @Embeddable to Address class
• Add @Embedded to UserDetails class above
the Address instance
Value Types and Embedding Objects

• Currently we have assumed that the member


variables inside the object can all go inside
single columns
Having objects inside objects or having collection objects inside model objects

• Currently we have assumed that the member variables inside the can
all go inside single columns
• What if one of these member variables were to be an object instead
of simple data type that can fit into a column and that object had
few member variables inside of them each of them having particular
values. How will you save that using Hibernate. What if one of them
were an Array, List, Set. How will we save that using Hibernate. That’s
what we will learn in this tutorial.
• Scenario 1 – User class instead of having an address String has an
address object.
• We will write a separate Address class and the Address class will have
Street, City, State, Pincode
• Our UserDetails class instead of having a simple String as an address
member variable it will have an instance of address object. How will
we save this
Value Types and Embedding Objects

 
Scenario 1 – User class instead of having an address String has an address object.

• As of now the simplest way to do this is to have each of these member variables of the address object inside
the user class also to have separate columns

• Now the user class has an address object and the address object has some member variables.
• We are going to treat the member variables of address object the same way as member variables as the user
class itself. We will assume that there is no address object its just Steet, City, State, Pin code are the four other
member variables of the user class itself. We would save it the way we would save four member variables.
Thus we are saying to have separate column for street, city ,state, pin. This is almost as if these member
variables are member variables of user class. It not as if there is another object and the member variables are
of that object. It is almost as if there is one class and these are flat member variables.

• This option works fine if the object inside the UserDetails class is a value object.
• When you are dealing with value objects you have a different approach versus when you are dealing with
entities itself. Well you can have an entity inside another entity. There is no stopping you from having say
another object here which is actually an entity but which is related to user object. You can have a member
variable which is another entity and that entity might have a meaning of its own and that happens to be inside
another entity.

• But that not the case when its come to address. Address does not have a meaning on its own. It has to be
associated with a user object otherwise there is no point of having an Address object. That’s what make an
address object a value object.

• This approach that we are going to take can be applied to value object.
Approach1 – treat the member variables of address object the same way as member variables as the user class itself
Entity and Value Object

• When dealing with hibernate we see two kinds of object


• 1. Entity 2. Value Object
• An entity is something that we saw earlier. That was the user class. User is
an entity. It has an object and needs to be saved in a separate table in the
DB. It an entity in the sense of word that its independent and it contains
data that provides meaning about itself. An entity has a meaning on its own

• A value object has data and even that has to be saved in the database but it
does not have any meaning of itself and provides meaning to some other
object. E.g. the address object with street city state pinc ode values all
populate. The address object as of itself does not have any meaning. It an
address of a User class. Without having a user object just an address does
not makes sense. It purpose in life is to provide value to the user object. Its
does
• not have a meaning on its own
Create Address Class
Create a new address class
 
package org.kaushik.javabrains.dto
import javax.presistance.Embeddable
@Embeddable
public class Address{
 
private String street;
private String city;
private String pincode;
private String Street;
//generate gettersandsetters 
}
Inoder to mark this as a valuetype and tell hibernate not to create a separate table for this I need
to use @Embeded. @Embeded which tells hibernate that this object needs to be embeddable
inside something else
Add Address Instance to UserDetails Class add annotation @Embedded

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@Embedded
private Address address;

//generate the getters and setters 


 
}
Setting Address in the User instance

package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session;

public class HibernateTest{


public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr = new Address();
addr.setStreet(“Street Name”);
addr.setCity(“City Name”);
user.setAddress(addr);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
}
}
Summary

• we have an address object and we have


embedded this object in our user details class.
• We had marked the address object as
@Embeddable and
• we had defined an instance of Address object in
UserDetails class and we had marked this instance
as @Embedded so that the fields of this Address
object get embedded in the UserDetails table that
was created.
• We have also set the address in user instance
user.setAddress(addr);
Attribute Override and Embedded Object Keys

• @Column(name=“column_name”)
The above annotation goes on top of the field whose
name you want to configure in the embeddable object
(Address object in this case)
• @AttributeOverride – this annotation goes on top of the
field whose name you want to override so that it does
not take the default name in the UserDetails
table(Company Address reference in the UserDetails
table.)
• Case: If you are embedding an object and that object
happens to be a primary key then you cannot use @Id
and @Embedded but we can use @EmbeddedID. This
annotation is for embedded objects as a primary key.
Configuring the Columns of Embedded Object in UserDetails Table

• How do I configure all the column of the Address object which is an


embeddable object. Say Address class has a field variable City. I want to
call City as City_Name in my User Details table. How can I configure the
city field of the Address object
• Method 1 – go to the embeddable object, then go to the city member
variable and on top of the member variable mention @Column
(name=City_name)
• Now I have the @Column annotation for each of these fields inside the
embeddable object. No matter where I am with this address object it’s
going to carry this configuration. I have used the Address object inside my
UserDetails class. The UserDetails table will have these column names that
I have configured inside this Embeddable object. Now I have another
object say Company object. I want to have Address as a member variable
of Company object. Then even the Company table would have these
column names. So it gets carried over no matter where you embed this
object
Configuring the Columns of Embedded Object Address.java

package org.kaushik.javabrains.dto
import javax.presistance.Embeddable
@Embeddable

public class Address{


@Column (name=”STREET_NAME”)
private String street;
@Column (name=”CITY_NAME”)
private String city;
@Column (name=”PIN_CODE”)
private String pincode;
@Column (name=”STATE”)
private String State; 
private String street;
//Generate getters and setters
}
Embedded Address in UserDetails Class using @Embedded
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@Embedded
private Address address;

//generate the getters and setters 


 
}
Main Method for testing Embedded Object

public class HibernateTest{


public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr = new Address();
addr.setStreet(“Street Name”);
addr.setCity(“City Name”);
user.setAddress(addr);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
}
}
Requirement of having two address objects inside UserDetails Class

• I have a requirement of having two address objects inside the same class.
Home address, office address. How would it work.
• We cannot have two columns in the same table with the same name.
• We can solve this overriding the default name when you are embedding.
• Now when I am embedding this home address, I don’t want this to take to
take Street_Name, I want it to have Home_Stree_Name. So I can override
the column names here so that it does not take the default.
• Second thing is if I have multiple such objects I can give unique names to
each of those objects so that there is no conflict. Then eacbe created for
this address object.
• How do i actually do the override. To override I use @AttributeOverride .
This helps me to reconfigure all the attributes that have been either
configured h of those objects can have a set of columns which are to here
or I can change the default behavior so that I can make it specific to my
needs and secondly I can make it distinct so that there is no overlap
between different objects.
@AttributeOverride
package org.javabrains.koushik.dto;
import javax.persistence.AttributeOverride

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@Embedded
@AttributeOverrides ({
@AttributeOverride (name=”street”, column=@Column(name=”HOME_STREET_NAME”)),
@AttributeOverride (name=”city”, column=@Column(name=”HOME_STREET_NAME”)),
@AttributeOverride (name=”state”, column=@Column(name=”HOME_STREET_NAME”)),
@AttributeOverride (name=”pincode”, column=@Column(name=”HOME_STREET_NAME”))
})
private Address homeAddress;
@Embedded
private Address officeAddress;
 
//generate the getters and setters
 }
main class
package org.koushik.hibernate
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr = new Address();
addr.setStreet(“Street Name”);
addr.setCity(“City Name”);
user.setHomeAddress(addr);
 
Address addr2 = new Address();
addr.setStreet(“Second Street Name”);
addr.setCity(“Second City Name”);
 
user.setOfficeAddress(addr2)
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 }
}
Special Case
• There is one special case where this userId the Primary Key of this model object
can itself be an embedded object.
• Let’s say I have an object which has first_name, last_name, soc_scurity_no,
login_id. A combination of all those is a primary key. Assume that we have few
member variables which put together forms a primary key e.g. userName, userId.
• We can use @Embedded but it would not work with @Id.
• we can use @EmbeddedID. This annotation is for embedded objects as a primary
key.
• In that case hibernate will treat a combination of all the member variables of the
objects as the primary key and If there is any repetition in all the values being same
for two different records. That’s when hibernate says that it not allowed. The object
itself and the comibnation of all the member variables has to be unique.
• If you are embedding an object and that object happens to be a primary key then
you cannot use @Id and @Embedded but we can use @EmbeddedID.
@EmbeddedId
package org.javabrains.koushik.dto;
import javax.persistence.AttributeOverride

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@EmbeddedId
 private loginName userId;
private String username
@Embedded
private Address officeAddress;
 //generate the getters and setters
 }
Saving Collections
• Having Collection of Objects in our entity class and persisting it in a separate table
• I want a collection of List of Address to be a member variable of the UserDetails class.
• I want a collection to be a member variable of the UserDetails class. Use Case – I want to
keep a track of all the addresses that the particular user has lived in over the years. I have
a list of addresses and I don’t know how many they will be so I cannot instantiate them
statically.
• Now we can have collections and hibernate does provides support for that. But lets take a
minute to think how this would work. If it’s a fixed number of objects well it makes sense
we can have fixed number of columns. Say we had Home Address and we had separate
column for them. Once that created that would do. But now I do not know how many
address objects I would be having . I could have 1, or 100. How would you have handled
when you designed the table. You would probably create a different table for the address
data and you would have probably reference the user. e.g. I have userid1 I have 5 address
for this user, I will insert 5 records for this user in a separate table called address table and
each of those 5 records will have userid1 associated with it as a foreign key.
• So will create a collection of addresses inside the UserDetails entity class and we will
instantiate it and we will see how hibernate deals with this.
• We will start with a set.
• @ElementCollection – This makes Hibernate know that this has to be treated as a
collection and should not be embedded as a table but as a separate table.
• Also Address is marked as @Embeddable
Creating a Collection inside the UserDetails Entity Class

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 private int userId
private String username
@ElementCollection
@JoinTable(name=”USER_ADDRESS”)
private Set<Address> listOfAddresses = new HastSet();
//NOTE: I cannot use implementation while we are declaring the set

//generate the getters and setters


 
}
Marking the Address Class as @Embeddable
package org.kaushik.javabrains.dto
import javax.presistance.Embeddable
@Embeddable
public class Address{
@Column (name=”STREET_NAME”)
private String street;
@Column (name=”CITY_NAME”)
private String city;
@Column (name=”PIN_CODE”)
private String pincode;
@Column (name=”STATE”)
private String State;
 
private String street;
//generate getters nad setters
}
Initializing the Address Objects and adding the Values to the Collection
package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session

public class HibernateTest{


public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr1 = new Address();
addr.setStreet(“First Street”);
addr.setCity(“First City”);
addr.setState(“First State”);
addr.setPinCode(“100001”)
 
Address addr2 = new Address();
addr2.setStreet(“Second Street”);
addr2.setCity(“Second City”);
addr2.setState(“Second State”);
addr2.setPinCode(“200002”)
 
user.getListOfAddresses().add(addr1);
user.getListOfAddresses().add(addr2);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
}
}
Summary
• Note: First it inserts username and userid into UserDetails table with userid as
primary key.
• Second it inserts into the sub table UserDetails_ListOFAddresses all the address along
with userid as a foreign key.
• I have a UserDetails Entity class and that entity class has a collection. The collection
happens to be a set here and I have annotated that as @ElementCollection.
• I have also defined the actual Address class which is the member of that collection
and I have annotated it as @Embeddable.
• Now the idea is that I can have a multiple addresses , a collection of Addresses for
every user entity. Now how does hibernate deal with it. Hibernate takes the actual
entity object and creates a record for that entity object in the entity table. And then
looks at how many addresses are there for this user class. Whatever is the size of this
collection say I have n number of object in the collection. First it creates a sub table
for this collection so that it can store all those elements and then depending on how
many members are there in this collection it creates so many records. Since its first
save the user object it knows what’s the user id. It adds the user id for all the sub
element that it has saved.
Configuring Collections and Adding Keys
• In the previous tutorial we wrote a collections of objects in our Entity class and we persisted it in a separate
table.
• We will look at the ways in which we can tweak the collection object here. We can tweak the way in which
hibernate saves this collection. We will also explore some advanced options.

• First thing is the name of the table. Hibernate has given this name for us. Its Classname_memberVariable i.e.
UserDetails_ListOfAddresses.
• I want to Tweak this as it’s not a user friendly name. I want to have the name as User_Address.
• All I do is use the annotation @JoinTable(name=”USER_ADDRESS”)

• Changing the name of the Join Table


• Changing the name of the join table UserDetails_ListOfAddresses
Hibernate has given this name for us –
I want change it to User_Address –
can be done by adding annotation @JoinTable(name=”USER_ADDRESS”) ontop of the collection declaration.

Changing the name of the Join Column


• Now the primary key in the join table UserDetails_ListOfAddresses is mentioned as UserDetails_userId which
is the default and I can override this by @JoinTable (name=”USER_ADDRESS”,
joinColumns=@JoinColumns(name=”USER_ID”)).

• NOTE: @JoinTable (name=”USER_ADDRESS”, joinColumns=@JoinColumns(name=”USER_ID”)).


Changing the name of the JoinTable & the JoinColumn

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@ElementCollection
@JoinTable (name=”USER_ADDRESS”, joinColumns=@JoinColumns(name=”USER_ID”)).
private Set<Address> listOfAddresses = new HastSet();
//NOTE: I cannot use implementation while we are declaring the set

//generate getters and setters


 
}
Define an Index or Id for Join table USER_ADDRESS mentioned in Previous Slide

• I want to define an index or an ID for the table User_Address i.e. I want to define an ID for a collection inside your entity class. In
order to have an index column I need to have a datatype that supports index. I cannot use a HashSet because there is no index
supported in the hash set.

• To do that I would need to change the Collection declaration from Set to ArrayList. Because you have indexes in ArrayList or Array

• Also I need to define the primary key configuration in the UserDetails class – use annotation @CollectionId.
This annotationis unique in a sense that it is not a JPA annotation but imported from org.hibernate.annotations.CollectionId

• This feature is not provided by JPA and is provided by Hibernate alone.


• In order to have a collection of objects as a member variable inside your entity class
• Change the data type of collection to something that supports indexes e.g. ArrayList
• I denfine @CollectionID annotation which tells that this collection should have an identifier. There are the attributes that the
@CollectionID expects.
• a. columns – what is the column that you want to define as primary key
• b. generator – how is the primary key to be generated
• c. type – what is the type of the primary key
• @GenericGenerator(name=”hilo-gen”, strategy=”hilo”

• @CollectionId (columns={@Column(name=”ADDRESS_ID”)} , generator=”hilo-gen”, type=@Type(type=”long”))

• Note: that the ID is not present in the Address class. So I cannot set the ID and it has to be auto generated. In order for the Id to be
auto generated I define a generator which is hilo(type of generator). Once I define a generator I can use it in many places. I use
this generator in @CollectionID in order to generate the primary key. Here the primary key will be ADDRESS_ID
• All these are hibernate generators
Define an Index or Id for Join table USER_ADDRESS mentioned in Previous Slide
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@ElementCollection
@JoinTable(name=”USER_ADDRESS”, joinColumns=joinColumn(name=”USER_ID”))
@GenericGenerator(name=”hilo-gen”, strategy=”hilo”)
@CollectionId (columns={@Column(name=”ADDRESS_ID”)} , generator=”hilo-gen”, type=@Type(type=”long”))
private Collection<Address> listOfAddresses = new ArrayList();
//generate getters and setters
}
main class
package org.koushik.hibernate
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session

public class HibernateTest{


public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr1 = new Address();
addr.setStreet(“First Street”);
addr.setCity(“First City”);
addr.setState(“First State”);
addr.setPinCode(“100001”)
 
Address addr2 = new Address();
addr2.setStreet(“Second Street”);
addr2.setCity(“Second City”);
addr2.setState(“Second State”);
addr2.setPinCode(“200002”)
 
user.getListOfAddresses().add(addr1);
user.getListOfAddresses().add(addr2);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
}
}
Proxy Object and Eager and Lazy Fetch Types

• In this tutorial we will look at what proxy objects


are and how hibernate provides proxy objects for us
• We will also understand what eager and lazy
fetching is.
• This is a very fundamental tutorial and lists the
basics of how Hibernate works.
• To recap we have alist of address objects in our user
entity and we are saving that as a separate table.
• I have persisted the user entity in the database and
I need to retrieve this.
•  
UserDetails class

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@ElementCollection
@JoinTable(name=”USER_ADDRESS”, joinColumns=joinColumn(name=”USER_ID”))
private Collection<Address> listOfAddresses = new ArrayList();
//NOTE: I cannot use implementation while we are declaring the set

//generate getters and setters


 
}
Retrieving user entity from the database
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr1 = new Address(); addr.setStreet(“First Street”); addr.setCity(“First City”); addr.setState(“First State”);
addr.setPinCode(“100001”)
 
Address addr2 = new Address(); addr2.setStreet(“Second Street”); addr2.setCity(“Second City”);
addr2.setState(“Second State”); addr2.setPinCode(“200002”)
 
user.getListOfAddresses().add(addr1); user.getListOfAddresses().add(addr2);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
user = null;
session = sessionFactory.openSession();
user=(userDetails)session.get(UserDetails.class, 1);
user.getListOfAddresses
 
}
}
 
Discussion on whether List of Addresses get pulled up on session.get(UserDetails.class, 1) or
when I do user.getListOfAddresses

• This user object has List inside it (ArrayList)which is the listOfAddresses).


• Now how would we normally get the list of addresses inside user object without using
hibernate.
• How would we get the user details. We would run a query and get the user data. The second
query would be to get the addresses of this user. So I have the userid as 1. I would run a
query to get all the addresses where the userid is 1.
• If I wanted a particular set of addresses I could restrict it in a where clause and get only those
addresses. If I wanted just the user information , I would just go to the user table and get the
user information.
• Now when I am doing the session.get() here what is getting pulled out. You are getting this
user object. This user object has an ArrayList of addresses.
• So the question is does the whole list of addresses get pulled up. If the answer is yes then
another question, say I have 100 addresses for a particular user. When I am pulling up the
user information do all those addresses get pulled up . If yes what is the cost i.e. what is the
performance impact.
• I don’t want all the addresses to be pulled up when I am only interested in the user name,
why would I want the addresses as well.
Discussion on whether List of Addresses get pulled up on
session.get(UserDetails.class, 1) or when I do user.getListOfAddresses

• To answer this question we will have to look at Fetch Strategy – Hibernate employs a strategy to solve this
problem. If you want to use just the user information you can ask hibernate not to pull up all the address
information. Infact that is the default behavior of hibernate unless you configure it otherwise.
• If I do a session.get(UserDetails.class, 1) it is not pulling up the list of addresses as well even though the user
object has list of addresses here. If you look at the state of User Object when the below line gets executed.
• user=(userDetails)session.get(UserDetails.class, 1);
• You will see that the addresslist is not initiated

• However the moment I run the getter method user.getListOfAddresses, that’s when hibernate goes and runs
another query to the DB and fetches the listOfAddresses.
• Now why does it do this way and how does it do this.
• Why – it you are just interested in user data. Say this user has few other info inside user details like phone
number, etc, and you are interested only that then there is no point in fetching the list ofaddresses. So you fetch
the list of addresses only when you are accessing the list of addresses. So the first time you use this getter it
would fetch the list of addresses.

• So it’s more efficient, doesn’t just pull up all the data that’s there. Say my UserDetails has 5 such lists like this
and each such list has 100 objects inside it. It’s going to take forever to get one object while I am just interested
in a name. Bec its going to pull all those list and all the data associated with the list and that’s going to be in
vain if you are not using it. So the why is fairly clear. You get it only when you use it. This kind of strategy is
called Lazy Initialization in Hibernate
Lazy/Eager Initialization
• Lazy Initialization – means that you do not initialize the entire
object, you only initialize the first level member variables of the
object. Then you initialize the list only when you access it.

• Eager Initialization ––you can configure hibernate to do that as


well. When you make the object use eager initialization, what
you are saying is hey hibernate i do not care how many lists are
there, I want you to fetch all the related data so if there is a list
in the user object then I want you to get all the values of that
list. This will take a lot of resources and lot of time, you should
do this only if you need it otherwise you stick to defaults which
is lazy initialization.
How Hibernate pulls all values when I am calling the getter method when
there is really nothing happening
• Hibernate does this by using a proxy class.
• What happening in the proxy class is, Hibernate instead of getting the actual object that you are looking for, it gets you a
proxy in the first time. It is a dynamic sub class of you actual object. You do a session.get(userclass, 1). What hibernate
does is instead of giving the user class directly which means pulling all values and then packaging in the userclass and then
handing it over to you, instead of doing that, what Hibernate does is it cleverly creates this proxy user class which is a
subclass of the user class and has the same methods. What the proxy user class does is instead of fetching the values and
populating it into the object and sending it back as a result of .get. What it does is it just probably fills in all the first level
values, say the list of addresses it does not get bec its goint to be a huge list, it gonna get this proxy user class created and it
gonna hand you the object of proxy user class not the actual user class. You would not know bec it implements the same
method. Now getId() would probably have parent.getID() call. So whatever code you would write would still work on your
object that you have got here but its not a pure userclass object it’s a proxy user class object.
• Similarly for getName() would probably do a parent.getName(), so when you call a getName() actually your code is getting
executed even though its through this proxy. But since your code is getting executed you do not have to worry about it.
What ever you call method gets executed which is fine.
• Consider the getListOfAddresses, instead of pulling all the values and handling itover it to you, you are given the proxy user
class which does not have the complete list of addresses.
• Lets says you made a call to getListOfAddresses, since you have the proxy object you will be making a call to the method of
the proxy user class, this method will have code to first fetch the values from db and populate the list of addresses. After it
does that then it does the parent.getListOfAddresses. After it gets all the values then it calls the parent method. So your
getter will run fine but before your getter runs this pulls up all the values from DB. This ensure two things
1) You don’t have to worry about what object you are getting. Your object that you get is still a user class, it fulfills the user
relation ship because you are having a sub class. But since you having a proxy it makes a call and gets the records just in
time and then it calls the parent objects methods. So that the consumer of the object is concerned they don’t have to be
worry about whether they have got a proxy or a an actual object and everything works fine. Hibernate is providing a proxy
and then returning an instance of the proxy.
Hibernate Proxy
User Class
getId()
getName()
getListOfAddresses()

Proxy User Class


getId()
getName()
getListOfAddresses()
Printing the size of list of addresses
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr1 = new Address(); addr.setStreet(“First Street”); addr.setCity(“First City”); addr.setState(“First
State”); addr.setPinCode(“100001”)
 
Address addr2 = new Address(); addr2.setStreet(“Second Street”); addr2.setCity(“Second City”);
addr2.setState(“Second State”); addr2.setPinCode(“200002”)
 
user.getListOfAddresses().add(addr1); user.getListOfAddresses().add(addr2);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
user = null;
session = sessionFactory.openSession();
user=(userDetails)session.get(UserDetails.class, 1);
System.out.println(user.getListOfAddresses().size());
 
}
}
 This should return two because we are saving two addresses
To test that this is a proxy object and not real object
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Address addr1 = new Address(); addr.setStreet(“First Street”); addr.setCity(“First City”); addr.setState(“First
State”); addr.setPinCode(“100001”)
 
Address addr2 = new Address(); addr2.setStreet(“Second Street”); addr2.setCity(“Second City”);
addr2.setState(“Second State”); addr2.setPinCode(“200002”)
 
user.getListOfAddresses().add(addr1); user.getListOfAddresses().add(addr2);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
user = null;
session = sessionFactory.openSession();
user=(userDetails)session.get(UserDetails.class, 1);
session.close()
System.out.println(user.getListOfAddresses().size());
 
}
}
When we close the session our proxy is not able to get the values and throws a LazyInitializationException
To overcome the problem in previous slide we make fetch type as eager as below

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@ElementCollection (fetch = FetchType.EAGER);
@JoinTable(name=”USER_ADDRESS”, joinColumns=joinColumn(name=”USER_ID”))
private Collection<Address> listOfAddresses = new ArrayList();
//NOTE: I cannot use implementation while we are declaring the set

//generate getters and setters


 
}
NOTE: Even though the session is close the value shows up as two when we run the HibrnateTest class.
One to One Mapping- One Entity inside another Entity
 

• The last few tutorials we have been looking at objects inside another object scenario. We have
explored a couple of scenarios there with one object being the entity and the object inside the
entity being value type. We saw how we could use hibernate to save those objects if there is one
instance of value type inside the entity we also looked at what if there is a collection of value type
inside the entity

• In this tutorial we will look at what happens if there is “One Entity inside another entity”
• This is what we have done so far. We have UserDetails Entity and inside that we have an element
collection of Address. Address is not an entity it’s a value type. We have looked at how to use
Hibernate to persist this entity if this address was just a single instance and also if it were a
collection.

• In this tutorial we look at


• An Entity inside another entity
• One to one mapping
• One to one mapping is a very common term that we use when we are designing databases. We
look at relationship between tables
• Summary
1. Create a new Entity class and declare it in hibernate mapping file
  2. Instantiate the Vehicle class in the main method and set the vehicle name and do a
session.save for vehicle.
3. Create an instance of Vehicle class inside the UserDetails class and declare the annotation
@OneToOne above the Vehicle instance.
4. Associate the vehicle with this user. By doing user.setVehicle(“vehicle”);
One to one mapping – UserDetails Entity class
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username

//generate getters and setters


 
}
 
One to one mapping – main method
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
 
SessionFactory sessionFactory = new
Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
sesion.getTransation.commit();
session.close();
 
 
}
}
One to one mapping – creating one more Entity class Vehicle
I will create one more entity class and I will have one to one mapping between the
UserDetails and that Entity class. I will take a simple example here. I will have a Vehicle
Entity class and I will have one to one mapping between UserDetails and the Vehicle object

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity // declaring this as Entity


public class Vehicle{
@ID @GeneratedValue // so that hibernate generates primary key here
private int vehicleId;
private String vehicleName;
// generate getters and setters
}
One to one mapping – adding the Vehicle Entity class to hibernate.cfg.xml
<session-factory>
<! -- Database connection settings -- >
<property name=”connection.driver_class”>org.h2.Driver</property>
<property name=”connection.url”>jdbc:h2:mem:db1; DB_CLOSE_DELAY=-1; </property>
<property name=”connection.username”>sa</property>
<property name=”connection.password”></property>
 
<! -- JDBC Connection Pool (Use the built in ) -- >
<property name=”connection.pool_size”>1</property>
 
<! -- SQL Dialect -- >
<property name=”dialect”>org.hibernate.Dialect.H2Dialect</property>
 
<! - - Disable the second level cache -- >
<property name=”cache.provider_class”>org.hibernate.provider.NoCacheProvider</property>
 
<! - - Echo all SQL to stdout -- >
<property name=”show_sql”>true</property>
Note: hibernate will print out all the SQL which it will generate
 
<! - - Drop and recreate the database schema on startup -- >
<property name=”show_sql”>true</property>
 
<! – Name the annotated entity class -- >
<mapping class="org.javabrains.kaushik.dto.UserDetails" />
<mapping class="org.javabrains.kaushik.dto.Vehicle" />
</session-factory>
One to one mapping
• Now, we can instantiate the Vehicle class in the main class
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
 Vehicle vehicle = new Vehicle();
vehicle.setVehicleName(“Car”);

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();


Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(vehicle);
sesion.getTransation.commit();
session.close();
 
 
}
}
• NOTE: so far we have not done any mapping here. Both Vehicle, UserDetails are independent objects
• There is no relation between the user and the Vehicle
One to one mapping – Establishing One to one Relationship between
UserDetails and Entity class
• NOTE: so far we have not done any mapping here. Both Vehicle, UserDetails are independent
objects
• There is no relation between the user and the Vehicle
• Now let’s run the main method
• It does an insert into UserDetails table and the Vehicle table. UserDetails table has userName
and userId, Vehicle table has vehicleName and vehicleId. So these two are two dependent
entities with no relation to each other. You can have any number of entities as you want. You
just have to mark them as entities. Then to have to do a session.save(of object of Entity).
Hibernate will create tables and insert them.
• Now we want to establish one to one relation between UserDetails class and the Vehicle
class. In order to do so I will have an instance of Vehicle class inside the UserDetails class and
generate getters and setters.
• If Vehicle was a value type then we could have declared Vehicle class as @Embeddedable and
the UserDetails class as @Embedded and the Vehicle columns would have come inside
UserDetails columns
• Here a vehicle is a separate Entity and it needs a separate table. Obviously we need to have a
mapping between User Details and Vehicle table. The way hibernate does it is by having a
column in the UserDetails table to point to the Vehicle table. So when mapping Entities we
need to use a different set of Annotations depending on the relation that we have. Here we are
trying to establish a one to one relationship. So we use the annotation @OneToOne in the
UserDetails class.
• Another thing that we need to do is to associate the vehicle with this user. By doing
user.setVehicle(“vehicle”);
Instantiating Entity class inside UserDetails class
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username
@OneToOne
private Vehicle vehicle
//generate getters and setters
 
}
Associating the Vehicle with the UserDetails class in the main method
• Now, we can instantiate the Vehicle class in the main class
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
 Vehicle vehicle = new Vehicle();
vehicle.setVehicleName(“Car”);

user.setVehicle(vehicle);

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();


Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(vehicle);
sesion.getTransation.commit();
session.close();
 
 
}
}
Note: when we run this a new column vehicle_vehicleId is created in the userDetails table
Note:@JoinColumn(name=“vehicle_id”) in the UserDetails table
One to Many Mapping

• One to Many Mapping


• In this tutorial we will see one to many relationship
• The example that we had was a UserDetails object and a Vehicle object
and we had a one to one mapping
• In this tutorial we will look at single UserDetails object with multiple
Vehicle objects so that establishes one to many relationship. It also
establishes a one to many relationship depending on how we are
looking at it.
• User to Vehicle – one to many
• Vehicle to user is many to one
• Summary
1. Create the Vehicle Entity Object and map it in hibernate.cfg.xml
2. . I declare @OneToMany in the UserDetails class and instead of
creating an instance of Vehicle class inside the UserDetails class I
declare a collection set of the generic type Vehicle and initialize it and
generate getters and setters in the same class.
3 Adding the Vehicle to the collection in the main class and save the
vehicle object in session.
Create the Vehicle Entity Object and map it in hibernate.cfg.xml
package org.javabrains.koushik.dto;

@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
 
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}
Mapping the Entity class in hibernate.cfg.xml
<session-factory>
<! -- Database connection settings -- >
<property name=”connection.driver_class”>org.h2.Driver</property>
<property name=”connection.url”>jdbc:h2:mem:db1; DB_CLOSE_DELAY=-1; </property>
<property name=”connection.username”>sa</property>
<property name=”connection.password”></property>
 
<! -- JDBC Connection Pool (Use the built in ) -- >
<property name=”connection.pool_size”>1</property>
 
<! -- SQL Dialect -- >
<property name=”dialect”>org.hibernate.Dialect.H2Dialect</property>
 
<! - - Disable the second level cache -- >
<property name=”cache.provider_class”>org.hibernate.provider.NoCacheProvider</property>
 
<! - - Echo all SQL to stdout -- >
<property name=”show_sql”>true</property>
Note: hibernate will print out all the SQL which it will generate
 
<! - - Drop and recreate the database schema on startup -- >
<property name=”show_sql”>true</property>
 
<! – Name the annotated entity class -- >
<mapping class="org.javabrains.kaushik.dto.UserDetails" />
<mapping class="org.javabrains.kaushik.dto.Vehicle" />
</session-factory>
Using @OneToMany in UserDetails class

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username;
@OneToMany
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
//generate getters and setters
 
}
Adding the Vehicle to the collection in the main class
package org.koushik.hibernate
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Vehicle vehicle = new Vehicle();
vehicle.setVehicleName(“Car”);
 
Vehicle vehicle2 = new Vehicle();
Vehicle2.setVehicleName(“Jeep”);
  
user.getVehicle().add(vehicle);
user.getVehicle().add(vehicle2);
 
 SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(vehicle);
session.save(vehicle2);
 sesion.getTransation.commit();
session.close();
 
}
}
table structure
• Three separate tables are created
• 1.USER_DETAILS
• 2. VEHICLE
• 3. USER_DETAILS_VEHICLE
• NOTE: Neither the USER_DETAILS has information about the
VEHICLE
• Nor the VEHICLE has information about the USER_DETAILS
• Instead hibernate creates the table USER_DETAILS_VEHICLE
and it has both the IDs i.e. USER_DETAILS_UserId and VEHICLE
_vehicleId of the above mention tables i.e. USER_DETAILS
• and VEHICLE
Now I can configure the JOIN_TABLE and the JOIN_COLUMN

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username;
@OneToMany
@JoinTable(name=”USER_VEHICLE”, joinColumns=@joinColumn(name=”USER_ID”),
inverseJoinColumns=@JoinColumn(name=VEHICLE_ID))
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
  //generate getters andtter s
}
 
}
Many to one Mapping

• Summay - Many to One Mapping


• Just like you have one to many in the UserDetails we can have many to
one relationship in the Vehicle class.
• You need to instantiate the UserDetails class in the Vehicle class
• You need to add the annotation @ManyToOne in the Vehicle class
• You need to set the user in the vehicle instance in the main class
vehicle.setUser(user);
vehicle2.setUser(user);
• By defining many to one relationship, just like i have one to many
relationship I can have a reverse relationship, so that when I pull up the
vehicle object , say i have a handle with Vehicle object I can use
vehicle.getUser , the proxy know that when I am doing a get user it needs
to go to the DB and pull up the record. Depending on whether I have the
user object or the vehicle I can the other object easily by using the
corresponding getters.
Creating a many to one relationship in the Vehicle class
@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
  @ManyToOne
private UserDetails user;
//generate getters and setters
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}
Setting the user to the Vehicle class
package org.koushik.hibernate
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
 
Vehicle vehicle = new Vehicle();
vehicle.setVehicleName(“Car”);
 
vehicle vehicle2 = new Vehicle();
vehicle2.setVehicleName(“Jeep”);
  
vehicle.setUser(user);
vehicle2.setUser(user);
 
  SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(vehicle);
session.save(vehicle2);
  sesion.getTransation.commit();
session.close();
 
}
}
Another way to represent one-to-many or a many-to-one relationship

• There is one other way to represent one-to-many or a many-to-one relationship and that
is that the object on the many side of the relationship has a reference to the other object.
Now my User table cannot have a column for vehicle id bec one user can have multiple
vehicles. But the vehicle table can have a userId col bec any vehicle will have only one
user. It’s a many to one as far as the vehicle side of the relationship is concerned. So I can
have a userid col in my vehicle table and I can do the mapping there itself without having
a separate table which has the mapping for the user and the vehicle id. So in this tutorial
we will have a quick look at that
• I need to say that Vehicle class needs to have a mapping of that relationship
• I go to the UserDetails class and for the annotation @OneToMany I have a property
called mappedBy which says where want the mapping to happen.
• @OneToMany(mappedBy=“user”)
• Then I will go to Vehicle class and under @ManyToOne, I will specify the
@JoinColumn(name=USER_ID). So I am naming the join column that I am creating inside
the Vehicle table itself. So once we putting this annotation hibernate knows that the
mapping is for this user and the join column is in the Vehicle table. So instead of creating a
new table it will create a column inside the Vehicle table and it will have the id of the user
saved here
• Instead of mapping the USER_ID with VEHICLE_ID in a separate table hibernate inserts the
User_ID in the Vehicle table and does not create a new table
UserDetails class with one-to-many relationship

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
  private int userId
private String username;
@OneToMany(mappedBy=“user”)
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
  // generate getters and setters
 }
Vehicle class with many-to-one relationship
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
@ManyToOne
@JoinColumn(name=USER_ID)
private UserDetails user;
 
//generate getters and setters
 
}
Many to Many

• In this tutorial we are going to look at many to many


relationship. There is only one way in which we can
represent many-to-many relationship. It has to have
a mapping table. Assume a scenario where this is a
kind of rental vehicle. The user can rent multiple
vehicles and vehicle can be rented by multiple users.
So you cannot have the mapping either in the
UserDetails table or the Vehicle table.It has to be a
separate table.
• Just like I have a vehicle collection inside the user
object, I need to have a user collection inside the
vehicle object
UserDetails class for many to many
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
  private int userId
private String username;
@ManyToMany
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
  //generate getter and setters
 }
Vehicle class for many to many
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
@ManyToMany
private Collection<UserDetails> userList = new ArrayList();
 
//generate getters and setters

 
}
Test Class for many to many
package org.koushik.hibernate
import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails;
import org.hibernate.Session
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");

vehicle vehicle = new Vehicle();


vehicle.setVehicleName(“Car”);
 
vehicle vehicle2 = new Vehicle();
vehicle2.setVehicleName(“Jeep”);
 
user.getVehicle().add(vehicle);
user.getVehicle().add(vehicle2);
 
vehicle.getUserList().add(user);
vehicle2.getUserList().add(user);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user); //object is saved
session.save(vehicle);
session.save(vehicle2);
sesion.getTransation.commit();
session.close();
}
}
Tables Created
• We have USER_DETAILS table having userName and userId and
• VEHICLE table having vehicleName and vehicleId
• Hibernate creates two mapping tables
• USER_DETAILS_VEHICLE having USER_DETAILS_userId and vehicle_vehicleId
• VEHICLE_USER_DETAILS having vehicle_vehicleId and userList_userId
• It’s actually doing two mappings. Hibernate does not know that it needs to do only one
mapping. We need to tell hibernate to map only one table
• We don’t need to have two different mapping, we can prevent this by giving
• @ManyToMany(mappedBy=”vehicle”) in the Vehicle class.
• This tells us that UserDetails is doing the mapping and the Vehicle class is not doing the mapping.
This helps us to get one table
• Also you can go to the user details table and you can specify the join table name and join column
name. Its as simple as saying @JoinColumn inside @JoinTable. We would have to have a join
column and an inverse join column. So you are nameing both the user id column as well asthe
vehicle id column. But note that since you have mentioned here that its mapped by the vehicle
of the other class your join table and join column configrations need to be inside user detaills
class.
@JoinTable(name=”USER_VEHICLE”, joinColumns=@joinColumn(name=”USER_ID”),
inverseJoinColumns=@JoinColumn(name=VEHICLE_ID))

• There are a few concepts which are common across all these three combinations and we will
look at these concepts in the next tutorial
Vehicle class with @MappedBy to prevent multiple mappings. The mapping
happens for the class not having @MappedBy

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
@ManyToMany(mappedBy=“vehicle”)
private Collection<UserDetails> userList = new ArrayList();
 
//generate getters and setters

 
}
Specifying @JoinColumn inside @JoinTable
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
  private int userId
private String username;
@ManyToMany
@JoinTable(name=”USER_VEHICLE”, joinColumns=@joinColumn(name=”USER_ID”),
inverseJoinColumns=@JoinColumn(name=VEHICLE_ID))

private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();


  //generate getter and setters
 }
Cascade Types and Other Things
• We have covered relationships between Entities namely
• One-to-one
• One-to-many
• Many-to-one
• Many-to-many
• in our previous few tutorials
• In this we will look at few concepts which are common
across these relationships. We will cover a lot of misc
concepts which kind of fit at different places
•  
• Suppose we have a many to one relationship
• We will take the example of the Vehicle class
Vehicle class with many to one relationship
package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
private UserDetails user;
 
//generate getters and setters
 
}
 
@NotFound

• Assume that this vehicle is not having an owner i.e. this vehicle is not yet
rented/purchased so there is no user for this vehicle. So now what would happen if
you had a many to one association here and say you had getters and setters for
getUser() and setUser(). Now image if your code would get the vehicle and would
try to do a getUser()
• Imagine that your code would try to do a get vehicle and then try to do a getUser()
and there was no association for this vehicle in the user mapping, say there is no
user for this vehicle, then hibernate would throw an exception. It would say hey I
don’t have a user for this vehicle so a getUser() for a vehicle object which does not
have a user would throw an exception
• So there is a way in which we can suppress this exception so that hibernate does
not come with an error every time data is not there and if it is common situation
for data not be present at all time then you can prevent the these exceptions that’s
coming up by using the annotation @NotFound(action=NotFoundAction.IGNORE)
• This is imported from org.hibernate.annotations
• So if your user is not found you are telling hibernate to just ignore it and not throw
an exception
HibernateCollections

Collection objects that hibernate supports


• Hibernate has its own internal data types that it maps to for the
collection objects that you are creating
• There are few semantic for collections that you are creating in hibernate
• Bag Semantic – uses List / ArrayList
• Bag Semantic with ID – uses List / ArrayList
• List Semantic – uses List / ArrayList
• Set Semantic – set Set
• Map Semantic – uses Map data type of java
• Note: the difference between List and a Bag is that the List can be
ordered, you can have a sorted list. For a bag it does not matter in which
order you get the data.
• You don’t have to worry about the semantics. We will be working with
one of these data types. Hibernate is using one of these semantics
behind the scenes in order to maintain a collection.
Cascade
• Cascade is applicable to all the relationships be it One –to-one, One-to-
many, Many-to-one, Many-to-many. We will have a look at what cascade
means here
• Suppose I have the program given below where I have a User. Lets suppose
this User has ten vehicles.
• So I will have all the ten Vehicle objects and I will assign the vehicle objects
to the user
• Now if I have to save the User, I will have to do a session.save(user)
• I will also have to do a session.save() of all the ten vehicles of the user.
• Saving all the vehicles will make the code look messy and it’s also a pain.
• Its not just for saving. Suppose you delete the user and you will have to go
ahead and delete all the vehicle associated with the user
• You should note that whatever operation you are doing for a user you will
have to do the same operation for all the vehicles. So a save, update,
create will affect all the vehicles so will pass all these vehicle objects to
session.save().
Cascade
• There is a way to avoid this and you can use something called a as a cascade.
• I have the UserDetails class and the Vehicle class here. This is the same class that we have been looking at in
the one to many tutorials. In the Vehicle class there is no backwards reference. From the vehicle class you
cannot go to the UserDetails class
• Here is our test class that we run. Now we have our user object here. We have two Vehicle objects. So we
assign the vehicle objects to this User. So car and jeep are assigned to this user. Now when I save this I am
saving user, vehicle1, vehicle2.
• If I save just the user and not the vehicle1 and vehicle2 i.e. not the car object and the jeep object. and I run the
main class , I get the TransientObjectException which means that you have an object reference that you are
trying to save but this object references another object that you have not saved. So we need to make sure that
those objects are save as well.
• So this is a problem. Why does hibernate not automatically save it. We know that this user has two
references vehicle and vehicle2. Why does hibernate not save it directly . This is bec vehicle, vehicle2 are also
entity. Hibernate cannot make this assumption and save the entity because that might be something you would
want to do differently. Sometimes you would want to save these entities automatically. You want to have a
control over it.
• It it were a collection object, if this were not an entity and it was a value type, then the whole purpose of this
vehicle would be for this user so it makes sense when this user is save you save the vehicle also.
• Since its an entity, thsese two vehicles have a life of its own, it not really bound by the user, so you wouldn’t
want an automatic save or any operation to happen. Thus hibernate gives a benefit of doubt and then it does
not do any automatic save and wants us to specify when and how this need to be saved. Which is fine and we
do a session.save() for all the vehicles

• The problem is If you have a huge list of vehicle objects you need to do a session.save() for all of them, which is
a pain.
• This is what we want to avoid by using a Cascade
Cascade
• So what I do is in the UserDetails wherever I have this reference @OneToMany. I will have to tell hibernate that
I do not want to save each and every object here. If you come across this collection and you have unsaved
objects when I am doing a save for this user class go ahead and save all the objects in the collection as well.
@OneToMany(Cascade=CascadeType.PERSIST)
• CascadeType.PERSIST tells hibernate that if you see any new entity inside this vehicle collection which has not
been saved when the user is being saved then go ahead and save them as well.
• In the main class instead of session.save(user) , we will call another method of session called session.persist(user)
• Persist kind of does the same thing what a save does but there are a few differences and this is something we will
explore in upcoming tutorials. But for now just make this change. This change session.persist() ties in with
@OneToMany(Cascade=CascadeType.PERSIST)
• So whenever persist happens cascade needs to happen.
• That ensures that this user is persisted
• If you want all the operations to happen cascaded you can choose. Instead of specify each and every operation
you can say cascasde everyting.
• @OneToMany(Cascade=CascadeType.ALL)
•  
• CascadeType.REMOVE – which does a cascade for delete operation
• CascadeType.MERGE – explore later
• CascadeType.DETACH - explore later
• CascadeType.PERSIST - explore later
• CascadeType.REFRESH- explore later
using @OneToMany(Cascade=CascadeType.PERSIST)in UserDetails class

package org.javabrains.koushik.dto;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue
import java.util.Collection;
import java.util.ArrayList;
import org.hibernate.annotations.Collectionid;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
@Table (name="USER_DETAILS")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
 
private int userId
private String username;
@OneToMany(Cascade=CascadeType.PERSIST)
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
//generate getters and setters
 
}
Vehicle class used in one to many
@Entity
public class Vehicle{
@ID @GeneratedValue
private int vehicleId;
private String vehicleName;
 
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}
using session.persists(user) in the main class
package org.koushik.hibernate
import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration;
import org.hibernaqte.koushik.dto.UserDetails; import org.hibernate.Session
public class HibernateTest{
public static void main(String args){
UserDetails user = new UserDetails();
user.setUserName("First User");
vehicle vehicle = new Vehicle();
vehicle.setVehicleName(“Car”);
 
vehicle vehicle2 = new Vehicle();
vehicle2.setVehicleName(“Jeep”);
 
user.getVehicle().add(vehicle);
user.getVehicle().add(vehicle2);
 
vehicle.getUserList().add(user);
vehicle2.getUserList().add(user);
 
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.persists(user);
sesion.getTransation.commit();
session.close();
}
}

You might also like