Hibernate Tutorial
Short Description
hibernate...
Description
Hibernate Tutorial - Hibernate 3 on Baby Steps Posted by Dinesh Rajput
This hibernate tutorial provide step by step instructions on using Hibernate 3.0. Hibernate is popular open source object relational mapping tool for Java platform. It provides powerful, ultra-high performance object/relational persistence and query service for Java. Actually Hibernate is much more than ORM Tool (Object - Relational Mapping) because today its provide lots of features in the persistence data layer. ORM means Objects to Relational Mapping i.e. Java Persistence Objects are mapped to Relational databases by using ORM tools. HIBERNATE : An ORM Tool
Used in the Data layer of the applications
Implements JPA (Java Persistence API) i.e its have set of standards that have been prescribed for any persistence of any implementation need to be satisfied to persistence rules in the java that given minimal change of codes means follow the all rules of persistence in later if any change in the ORM tools with minimum change in the code.
Why We Have to Use ORM Tools?
Here there is one problem to object save in to relational database each entity of the object save individually to the database table in the associated columns. It is more times taken and complex in case of lots of user objects to be save into the database table.
When Inserting into database. Object's Property ID set to ID column Object's Property Name set to Name Column Object's Property Address set to Address Column Object's Property Phone set to Phone Column Object's Property Date of Birth set to DOB Column When Fetching Result Set from Database Table. Column ID's Value set to Object's ID Property Column Name's Value set to Object's Name Property Column Address's Value set to Object's Address Property Column Phone's Value set to Object's Phone Property Column DOB's Value set to Object's Date of Birth Property
Hibernate Architecture : Chapter 2 Hibernate Architecture and API
Configuration: It represents a configuration or properties file for Hibernate. The Configuration object is usually created once during application initialization. The Configuration object reads and establishes the properties Hibernate uses to get connected to a database and configure itself for work. A Configuration object is used to create a SessionFactory and then typically is discarded. SessionFactory :The SessionFactory is created from a Configuration object, and as its name implies it is a factory for Session objects.The SessionFactory is an expensive object to create. It, like the Configuration object, is usually created during application start up. However, unlike the Configuration object, It should be created once and kept for later use. The SessionFactory object is used by all the threads of an application. It is a thread safe object. One SessionFactory object is created per database. Multiple SessionFactory objects (each requiring a separate onfiguration) are created when connecting to multiple databases. The SessionFactory can also provide caching of persistent objects. -Dinesh
Session:Session objects provide the main interface to accomplish work with the database. Persistent objects are saved and retrieved through a Session object. A Session object is lightweight and inexpensive to create. A Session object does the work of getting a physical connection to the database. Session objects maintain a cache for a single application thread (request). Session objects are not thread safe. Therefore, session objects should not be kept open for a long time.Applications create and destroy these as needed. Typically, they are created to complete a single unit of work, but may span many units. -Dinesh Transaction: represents unit of works. Query and Criteria objects are used to retrieve (and recreate) persistent objects.
Setting Up Hibernate3 To Eclipse : Chapter 3
In this tutorial you will see how to configure Hibernate to Eclipse or STS or MyEclipse. 1. Download Eclipse Latest version and install in your machine. 2. Download Hibernate3 Latest Version. 3. Download MySQL database Latest version. 4. Download JConnector (MySQL Database Driver) Step 1 : Now open Eclipse you get following window-
Step 2: Go to File->New->Java Project
Step 3: Click on Java Project you will get
Step 4: Click Next -> Finish you will get
Step 5:Right Click on Hibernate Project->go to Property ->Java Build Path->Library->Add Library
Step 6: Click on User Library ->Next->User Libraries.. on New window click on New a pop up of new window is open and fill User Library Name on the Text Field and Click on OK.
Step 7: Click on Add JARs.. go to specific path of the window where you are save Hibernate Zip file and add following required jar to your Application antlr-2.7.6
dom4j-1.6.1
hibernate3
hsqldb
javassist-3.4.GA
jta-1.1
slf4j-api-1.5.6
slf4j-simple-1.5.6
commons-collections-3.1
Finally you will get Hibernate Library in your application
Step 8 : Now install MySQL Database on your machine and add driver library to your application
Go to Project Property->Java Build Path->Library->Add External JARs..->Select Driver jar file>click finish
Now your application fully configured with all required libraries.
First Hibernate Application using Annotation : Chapter 4 Lets we start on this topics. First we will see what is the process of using database without using Hibernate. Saving Without Hibernate -> JDBC Database configuration
The Model Object
Service method to create the model object
Database Design
DAO method to use saving the model object to the database using SQL queries. With Hibernate Way-> JDBC Database Configuration -> Hibernate Configuration
The Model Object -> Using Annotation
Service method to create the model object -> Using the Hibernate API
Database Design -> Not Needed
DAO method to use saving the model object to the database using SQL queries -> Not needed Now as above steps of using hibernate, firstly we have to create Hibernate Configuration file. Step 1: File Name -> hibernate.cfg.xml in src folder of the application
Now we need to type all the detail related to MySQL database so we can use in our application. hibernate.cfg.xml com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB username password 1 org.hibernate.dialect.MySQLDialect
thread org.hibernate.cache.NoCacheProvider true create Here below property configure driver of the specific database com.mysql.jdbc.Driver Next line we configure the Database connection url suppose we want to connect the database name hibernateDB jdbc:mysql://localhost:3306/hibernateDB Next two lines set the user name and password of the connecting database hibernateDB username password Next line configure Dialect of the database MySQL, every database has its own Dialect. What is Dialect? means Dialect is configuration specify here so hibernate knows whats kind of language we are used and what type database we are used. we can say it is database dependent. It connects the database specific query language which we want to use. org.hibernate.dialect.MySQLDialect The below line configured the model class name UserDetails its object we want save on the database hibernateDB Now step 1 is over now we move to another step Now we have to create a Model class Step 2: UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class UserDetails { @Id private int userId; 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; } } Here @Entity means it telling hibernate this class treat as entity and need to save it the database. and @ID means it telling hibernate this property treat as primary key of the table. these are two minimum required annotation we have use for saving the object in the database. Now we move to next step create service method to save the model object in the database. Using the Hibernate API Create a session factory
create a session from the session factory
Use the session to save model objects Step 3: HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { public static void main(String[] args) { //Create the model object UserDetails user = new UserDetails(); user.setUserId(1); user.setUserName("Dinesh Rajput"); // Create Session Factory Object using Annotation Configuration SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //Create Session object from session factory object Session session = sessionFactory.openSession(); session.beginTransaction(); //Use the session to save model objects session.save(user); session.getTransaction().commit(); session.close(); } } Now run application now we get a Table with name UserDetails as its model class name with two columns name are ID andUserName as class property name.
Next Chapter we will write hibernate application using mapping file for the model class
First Hibernate Application Using Mapping File : Chapter 5 In this chapter we will learn about how to use configuration file of the model class in stead of Annotation as used in the previous chapter and also learn about how to define model class property in the XML configuration fine or object mapping file(.hbm.xml). As previous chapter we have write the model class UserDetalis.java package com.sdnext.hibernate.tutorial.dto; public class UserDetails { private int userId; 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; } }
Mapping the UserDetalis Object to the Database UserDetails table The file userdetails.hbm.xml is used to map userDetail Object to the UserDetails table in the database. Here is the code foruserdetails.hbm.xml: Configuring Hibernate: here some change is required in the configuration file because we are used mapping file in stead of Annotation. hibernate.cfg.xml: com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB username password 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
Here we are used mapping resource in stead of mapping class. Developing Code to Test Hibernate example: Now there are three steps for using Hibernate API Create the session factory
Create the session object from the session factory
Saving the model object using session object HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { public static void main(String[] args) { //Create the model object UserDetails user = new UserDetails(); user.setUserId(1); user.setUserName("Dinesh Rajput"); // Create Session Factory Object - using configuration object SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); //Create Session object from session factory object Session session = sessionFactory.openSession(); session.beginTransaction(); //Use the session to save model objects session.save(user); session.getTransaction().commit(); session.close(); } } Now you can run the application and see the result. So in this topic we see how to use Mapping file to map the Model Object to relational database table.
In the Next Chapter We will Described the O/R Mapping file in details.
What is Hibernate O/R Mapping : Chapter 6 Hello Friends In Last chapters you learned about how to write our first hibernate application, there are two approach we have used for that--1. Using Annotation for Model Class Object Mapping
2. Another way Using Hibernate O/R Mapping file(.hbm.xml) for Model Class Object Mapping. In the last example we created userDetails.hbm.xml to map UserDetails Object to the UserDetails table in the database. Now let's understand the each component of the mapping file. To recall here is the content of userDetails.hbm.xml: 1. element: The first or root element of hibernate mapping document is element. Between the tag class element(s) are present. 2. element: The element maps the class object with corresponding entity in the database. It also tells what table in the database has to access and what column in that table it should use. Within one element, several mappings are possible. 3. element: The element in unique identifier to identify an object. In fact element map with the primary key of the table. In our code : primary key maps to the ID field of the table UserDetails. Following is the attributes of element name - Property name of the persistence model class
type - The java data type used for that property
column - Name of the column for that property of the persistence object
unsaved-value - This is the value used to determine if a class has been made persistent. If the value of the id attribute is null, then it means that this object has not been persisted. 4. element: Used to create primary key for new record, there are some commonly used generators type given below... Increment- used to generate primary keys of type long, short or int that are unique only.
Sequence - used to generate primary keys for DB2, Oracle, SAP Database.
Assigned - is used when application code generates the primary key.
Native
- selects identity, sequence or hilo depending upon the capabilities of the underlying db.
Identity - supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int.
Uuid - Unique use ID of 128 bits generated from using algorithm and return type is String
hilo - generated by the hi/lo Algorithm
seqhilo - generated by the hi/lo Algorithm according to sequence of database
select - select from database triggered value
foreign - associated with the other model objects
5. element: define standard Java attributes and their mapping into database schema. That is all about the mapping file for O/R mapping. I hope you was understand its all elements and its working in the hibernate.
Using Annotations in Hibernate vs Configuration files : Chapter 8 ANNOTATIONS VS. XML Since Java adopted annotations, I’ve heard a lot of discussion around whether to prefer annotations over external configuration files (often XML) and vice versa.
I think the decision boils down to two criteria: 1) Can annotations simplify the metadata? 2) Can changes to the metadata break behavior in your application? If annotations do not reduce the amount of metadata that you have to provide (in most cases they do), then you shouldn’t use annotation. For example, Hibernate mappings are often in XML, but annotations often provide the ability to specify the same mappings with significantly less metadata. Any changes you make to your mappings (whether in XML or annotations) could potentially be behavior breaking. You’re not going to change your mappings dynamically at run-time, are you? So, annotations seem like a much better choice. [Note: I might consider using XML metadata for Hibernate when mapping to a legacy database because the annotations can often become bulky. Also, you are forced to use XML if you want to map the classes against two different databases with different schema. I haven't heard of a way to specify two mutually exclusive sets of Hibernate annotations on my classes. Even if this did exist it would be complex, which violates my first criterion for selecting annotations over XML.]
MAPPING:
Mapping file is the heart of hibernate application.
Every ORM tool needs this mapping, mapping is the mechanism of placing an object properties into column’s of a table.
Mapping can be given to an ORM tool either in the form of an XML or in the form of the annotations. The mapping file contains mapping from a pojo class name to a table name and pojo class variable names to table column names. While writing an hibernate application, we can construct one or more mapping files, mean a hibernate application can contain any number of mapping files. generally an object contains 3 properties like Identity (Object Name)
State (Object values)
Behavior (Object Methods) But while storing an object into the database, we need to store only the values(State) right ? but how to avoid identity, behavior.. its not possible. In order to inform what value of an object has to be stored in what column of the table, will be taking care by the mapping, actually mapping can be done using 2 ways, XML Annotations. Actually annotations are introduced into java from JDK 1.5
Now we will look how to relate XML Mapping to Annotation Mapping a class UserDetails to Table USER_DETAIL in XML -
Now Mapping a class UserDetails to Table USER_DETAIL in Annotation -@Entity @Table (name="USER_DETAIL") public class UserDetails{}
here @Entity declares the class as an entity (i.e. a persistent POJO class) @Table is set at the class level; it allows you to define the table, catalog, and schema names for your entity mapping. If no@Table is defined the default values are used: the unqualified class name of the entity. Mapping primary key USER_ID of table to property userId of class UserDetails in XML
Mapping primary key USER_ID of table to property userId of class UserDetails in Annotation @Entity @Table (name="USER_DETAILS") public class UserDetails { @Id @Column(name="USER_ID")
private long userId; } here @Id declares the identifier property of this entity. The class UserDetails is mapped to the USER_TABLE table, using the column USER_ID as its primary key column. The column(s) used for a property mapping can be defined using the @Column annotation. Use it to override default values . Id Generator Class Mapping in XML
Id Generator Class Mapping in Annotation @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private long userId; Different GenerationType Enum Properties....
AUTO - either identity column, sequence or table depending on the underlying DB
TABLE - table holding the id
IDENTITY - identity column
SEQUENCE - sequence
identity copy - the identity is copied from another entity
@GeneratedValue Provides for the specification of generation strategies for the values of primary keys. Enum GenerationType Defines the types of primary key generation strategies. Mapping Column to the property of class in XML
Mapping Column to the property of class in Annotation @Column(name="USER_NAME") private String userName; @Column- provides the name of the column in a table if it is different from the attribute name. (By default, the two names are assumed to be the same.) More JPA Annotations for Class Field: @Basic - The use of the Basic annotation is optional for persistent fields and properties of these types. If the Basic annotation is not specified for such a field or property, the default values of the Basic annotation will apply. Example-
@Basic private String userName; @Transient - using when if you want skip any field of entity class to save in the database. Example@Transient private String middleName; @Embedded- using when if property or field of persistence class is Embeddable persistence class. Example- class Address{ @Column(name="STREET")
@Embedded private Address address; @ElementColllection- Defines a collection of instances of a basic type or embeddable class. Must be specified if the collection is to be mapped by means of a collection table. Example@ElementCollection private Collection lisOfAddresses = new ArrayList(); @Id- Specifies the primary key of an entity. Example@Id private long userId; @EmbeddedId- composite primary key of an embeddable class. Example@Embeddable Class Address{ @EmbeddedId private int addressId; ------} @Version- Specifies the version field or property of an entity class that serves as its optimistic lock value. The version is used to ensure integrity when performing the merge operation and for optimistic concurrency control. Example-
@Version private int addressId; @Temporal- This annotation must be specified for persistent fields or properties of type java.util.Date andjava.util.Calendar. Example@Column(name="JOIN_DATE") @Temporal(TemporalType.DATE) private Date joinDate;
Here we will learn about hbm2ddl Configuration in the hibernate configuration file (hibernate.cfg.xml). Actually hbm2ddl Configuration means hibernate mapping to create schema DDL (Data Definition Language). create Automatically validates or exports schema DDL to the database when the SessionFactory is created. With create-drop, the database schema will be dropped when the SessionFactory is closed explicitly. com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB username password 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
Here create means schema DDL created every time when SessionFactory Object is created. UserDetails.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Entity; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="USER_TABLE") public class UserDetails { @Id @Column(name="USER_ID") private int userId; @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; } } Now we run this example-public class HibernateTestDemo { public static void main(String[] args) { //Create the model object UserDetails user1 = new UserDetails(); UserDetails user2 = new UserDetails(); user1.setUserId(1); user1.setUserName("Dinesh Rajput"); user2.setUserId(2); user2.setUserName("Anamika Rajput");
// Create Session Factory Object - using annotation configuration object SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //Create Session object from session factory object Session session = sessionFactory.openSession(); session.beginTransaction(); //Use the session to save model objects session.save(user1); session.save(user2); session.getTransaction().commit(); session.close(); } } Run this example-log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Now we get following table structure--
Again we running the following examplepublic class HibernateTestDemo { public static void main(String[] args) { //Create the model object UserDetails user1 = new UserDetails(); UserDetails user2 = new UserDetails(); user1.setUserId(3); user1.setUserName("Dev Rajput"); user2.setUserId(4); user2.setUserName("Sweety Rajput"); // Create Session Factory Object - using annotation configuration object SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //Create Session object from session factory object Session session = sessionFactory.openSession(); session.beginTransaction(); //Use the session to save model objects session.save(user1); session.save(user2);
session.getTransaction().commit(); session.close(); } } Run this example-log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Now we get the following table schema--
Here we see that the previous data is destroyed when we are using in the hibernate.cfg.xml file using the following line. create Here hbm2ddl.auto-->create -Always create new schema hbm2ddl.auto-->update -Update existing schema Now we are replacing above line with the update public class HibernateTestDemo { public static void main(String[] args) { //Create the model object UserDetails user1 = new UserDetails(); UserDetails user2 = new UserDetails(); user1.setUserId(1); user1.setUserName("Dinesh Rajput"); user2.setUserId(2); user2.setUserName("Anamika Rajput"); // Create Session Factory Object - using annotation configuration object SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //Create Session object from session factory object Session session = sessionFactory.openSession(); session.beginTransaction(); //Use the session to save model objects session.save(user1); session.save(user2); session.getTransaction().commit(); session.close(); } }
Run this example-log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?) Now we get the following table schema...
here we are looking the table USER_DETAILS only updated not again created.
Retrieving Objects in Hibernate using session.get : Chapter 10 We'll look at one of the several ways we can fetch data from the database using Hibernate: the session.get method. Now look following example... UserDetails.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table (name="USER_TABLE") public class UserDetails { @Id @Column(name="USER_ID") private int userId; @Column(name="USER_NAME") private String userName; public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; } public String toString() { return "[User Name: "+userName+"User Id: "+userId+"]"; } } This is user domain persistence class UserDetails to store data into table USER_TABLE with columns name USER_ID and USER_NAME corresponding persisting field userId and userName respectively. Now we have to configure hibernate configuration file. hibernate.cfg.xml com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB root root 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true update
here we are using MySql database hibernateDB. Now we running the code with following class file HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //Creating first user user.setUserId(1); user.setUserName("Dinesh Rajput"); UserDetails user2 = new UserDetails();//Creating second user user2.setUserId(2); user2.setUserName("Anamika Rajput"); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //Creating a session factory object Session session = sessionFactory.openSession(); //Creating a session object for inserting users object to the database table USER_TABLE session.beginTransaction(); //Open the transaction of session object to do something session.save(user); //Inserting or Saving the first user object session.save(user2); //Inserting or Saving the second user object session.getTransaction().commit();//Close the transaction of session object after to do something session.close(); //Close the session object performing saving event to database user = null; //Now getting a user object from database table from session object session = sessionFactory.openSession(); //Creating a new session object for fetching user object session.beginTransaction(); //Again Open the transaction of the session object user = (UserDetails) session.get(UserDetails.class, 1); //we get user object from session object using method session.get(Class arg1, Serializable arg2) here arg2 is primary key or id of the fetching object and arg1 is the what the model object we want to retrieve from database.
System.out.println(user); } } Here after running this code we get following output... log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_TABLE (USER_NAME, USER_ID) values (?, ?) Hibernate: insert into USER_TABLE (USER_NAME, USER_ID) values (?, ?) Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_TABLE userdetail0_ where userdetail0_.USER_ID=? [User Name: Dinesh Rajput User Id: 1]
Hibernate Update Query : Chapter 11 In this tutorial we will show how to update a row with new information by retrieving data from the underlying database using the hibernate. Lets first write a java class to update a row to the database. Create a java class: here we update the value of the field name userName with corresponding column name is USER_NAME in the database tableUSRE_TABLE.
In the above table we want to update the value of the USER_NAME column of the USER_TABLE table associated user model object which userId = 2 current value of the userName is 'Anamika Rajput' update to userName='Sweety'. Look the following class file. HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = null; SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); user = (UserDetails) session.get(UserDetails.class, 2); //Retrieving object which we want to update user.setUserName("Sweety"); //Set the updated userName to the model field session.update(user); //Update to the database table session.getTransaction().commit(); System.out.println("Updated User ->"+user); session.close(); } } Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_TABLE userdetail0_ where userdetail0_.USER_ID=? Hibernate: update USER_TABLE set USER_NAME=? where USER_ID=? [Updated User -> User Name: Sweety User Id: 2]
Now we get the following updated table...
We are looking the value of the USER_NAME column updated from 'Anamika Rajput' to 'Sweety' in the USER_TABLE table.
Hibernate Delete Query : Chapter 12 In this lesson we will show how to delete rows from the underlying database using the hibernate. Lets first write a java class to delete a row from the database. Create a JAVA Class for this: here we give the code of java class HibernateTestDemo.java which we will delete a row from the USER_TABLE table using the query "delete from USER_TABLE where USER_ID = 2"
Following is USER_TABLE:
package com.sdnext.hibernate.tutorial; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); Session session = sessionFactory.openSession();
session.beginTransaction(); String sql = "DELETE FROM UserDetails WHERE USER_ID = 2"; Query query = session.createQuery(sql); int row = query.executeUpdate(); if (row == 0) System.out.println("Doesnt deleted any row!"); else System.out.println("Deleted Row: " + row); session.getTransaction().commit(); session.close(); } } Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: delete from USER_TABLE where USER_ID=2 Deleted Row: 1
Now we look the following table structure---
Value Types & Embedding Objects in Hibernate : Chapter 13
We’ll learn the difference between Entity type objects and Value type objects. We’ll use the @Embeddable annotations to embed a value type object into our Entity class. "An object of value type has no database identity; it belongs to an entity instance and its persistent state is embedded in the table row of the owning entity. Value types don't have identifiers or identifier properties" Now In short we look the following points... Object of Entity Type : has its own database identity Object of Value Type : belongs to an entity, and its persistent state is embedded in the table row of the owning entity. Value types don't have identifiers or identifier properties. We look following example of Object of Entity Type: @Entity @Table(name="USER_TABLE") public class UserDetails{ @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="USER_ID", type="INTEGER") private long userId; @Column(name="USER_NAME", type="String") private String userName; @Column(name=USER_ADDRESS, type="String") private String address; @Column(name="USER_PHONE", type="INTEGER") private long phone; @Column(name="DOB", type="TIMESTAMP") private Date dob; }
In Above table we saw that type of the all fields of the class USER CLASS have database entity type object. ID is INTEGER type Name is VARCHAR type ADDRESS is VARCHAR type Phone is BIG INTEGER type DOB is TIMESTAMP type All are the Entity Type Objects. Now We look following example of Object of Value Type:
@Entity @Table(name="USER_TABLE") public class UserDetails{ @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="USER_ID", type="INTEGER") private long userId; @Column(name="USER_NAME", type="String") private String userName; @Column(name=USER_ADDRESS, type="??????") //What should be type for database private Address address; @Column(name="USER_PHONE", type="INTEGER") private long phone; @Column(name="DOB", type="TIMESTAMP") private Date dob; } Now lets see table structure for that...
here USER CLASS have a field Address type of the Value type object means in the database there are no meaning of Address type object. Address type object have the four other fields like. 1. Street 2. City
3. State 4. Pin code VALUE TYPE OBJECT APPROACH:> Here there are one approach to save the value the Address Object save to the USER TABLE is the save the individually fields of this object to the separate columns of the USER TABLE. As following
This scenario is working in the hibernate only one condition is Address Object should be a Value Object (means there is no meaning to itself its provide the meaning to the entity object). In this approach there are some problems are 1. Table complexity 2. Data Redundancy 3. User may have multiple Address like home address and office address etc. Look the above example in the code... Address.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable //for value object it is not is entity object. Value object means does not have real meaning for self individually.
public class Address { @Column(name="STREET_NAME") private String street; @Column(name="CITY_NAME") private String city; @Column(name="STATE_NAME") private String state; @Column(name="PIN_CODE") private String pincode; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getPincode() { return pincode; } public void setPincode(String pincode) { this.pincode = pincode; } public String toString() { return " {Street: "+street+" City: "+city+" State: "+state+" Pincode: "+pincode+" }"; } } @Embeddable: Target: Classes Defines a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity. Each of the persistent properties or fields of the embedded object is mapped to the database table for the entity. UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.Date; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table (name="USER_TABLE") public class UserDetails { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="USER_ID") private int userId; @Column(name="USER_NAME") private String userName; @Embedded //For value type object private Address address; @Column(name="USER_PHONE") private String phone; @Column(name="DOB") private Date dob; public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } public int getUserId() { return userId; } public String toString()
{ return "[User Name: "+userName+"User Id: "+userId+" User Address "+address+" Use phone " +phone+" ]"; } } hibernate.cfg.xml com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB root root 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user1 = new UserDetails(); //create first user UserDetails user2 = new UserDetails(); //create second user user1.setUserName("Dinesh Rajput"); user2.setUserName("Anamika Rajput"); Address address1 = new Address(); //create first value type object for entity type object user1 address1.setStreet("K Block House No. 403"); address1.setCity("Mangol Puri"); address1.setState("New Delhi"); address1.setPincode("110083"); user1.setAddress(address1); Address address2 = new Address();//create second value type object for entity type object user2 address2.setStreet("Film City"); address2.setCity("Noida"); address2.setState("UP"); address2.setPincode("201301"); user2.setAddress(address2); user1.setDob(new Date()); user1.setPhone("+91-9953423462"); user2.setDob(new Date()); user2.setPhone("+91-9973423462"); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create a session factory object Session session = sessionFactory.openSession(); // create session object from session factory session.beginTransaction(); //begin transaction for this session session.save(user1); //save the first user session.save(user2); //save the second user session.getTransaction().commit(); //commit the transaction the session session.close(); //close the session } }
OUTPUT: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_TABLE (CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME, DOB, USER_PHONE, USER_NAME) values (?, ?, ?, ?, ?, ?, ?) Hibernate: insert into USER_TABLE (CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME, DOB, USER_PHONE, USER_NAME) values (?, ?, ?, ?, ?, ?, ?)
Attributes Override: Here we have seen that an Entity Type Object USER has a Value Type Object(or Embeddable Object ) ADDRESS with corresponding fields name street, city, pin-code and state save to the database table USER_TABLE with value type object's column name (CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME). But here some problems, suppose this user object have two types of addresses as like Local Address and Permanent Address then how to manage the column names of these value type objects in the database table USER_TABLE. To overcome this problem we have to override the Attributes of the Value type objects. Lets see how to get in the code... UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.Date; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.Table; @Entity @Table (name="USER_TABLE")public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME")
private String userName; @Column(name="DOB") private Date joinDate; @Column(name="ADDRESS") @Embedded @AttributeOverrides({ @AttributeOverride(name="street", column=@Column(name="HOME_STREET_NAME")), @AttributeOverride(name="city", column=@Column(name="HOME_CITY_NAME")), @AttributeOverride(name="state", column=@Column(name="HOME_STATE_NAME")), @AttributeOverride(name="pincode", column=@Column(name="HOME_PIN_CODE"))}) private Address homeAddress; @Embedded private Address permanentAddress; @Column(name="Phone") private String phone; public int getUserId() { return userId; } public Address getHomeAddress() { return homeAddress; } public void setHomeAddress(Address homeAddress) { this.homeAddress = homeAddress; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob= dob; } public Address getPermanentAddress() { return permanentAaddress; } public void setPermanentAddress(Address permanentAddress) { this.permanentAddress = permanentAddress; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone= phone; }
public String toString() { return "[User Name: "+userName+"\n Permanent Address: "+permanentAddress+"\n Home Address: "+homeAddress+"\n Date of Birth: "+dob+"\n Phone: "+phone+"]"; } } Now run the following code of the class file.. HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //create an user is entity type object //user.setUserId(1); user.setUserName("Dinesh Rajput"); Address address = new Address(); //create an value type object of address class for home address address.setStreet("Block House No"); address.setCity("MangolaPuri"); address.setState("New Delhi"); address.setPincode("110089"); user.setHomeAddress(address); //set the home address Address address1 = new Address();//create another value type object for the permanent address address1.setStreet("Film City"); address1.setCity("Noida"); address1.setState("UP"); address1.setPincode("201301"); user.setPermanentAddress(address1);//set the permanent address user.setDob(new Date()); user.setPhone("9999222211"); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create a session factory object Session session = sessionFactory.openSession(); //create a session object session.beginTransaction(); //transaction object start session.save(user); // save the entity type object user to the database
session.getTransaction().commit(); //commit the transaction object session.close(); //close the session } } After running the above code we will get the following table structure...
Saving Collections in Hibernate : Chapter 14 Now we’ll learn about the Collection in the hibernate. In previous chapter we learned about Embedding value type object. Now what will be do when there are a lots of embeddable objects instead of the single embeddable objects, In previous we have used two embeddable objects in the UserDetails class.
Suppose we want to keep tracks all addresses of an user, so think about one minute how to get. Lets we will using the Collection for that. 1. In this code snip User has one address class UserDetails{ ----private int userId; ----private Address address; ----}
2. In this code snip User has two addresses class UserDetails{ ----private int userId; -----
private Address address1; private Address address2; ----}
3. In this code snip User has more than two addresses class UserDetails{ ----private int userId; ----private Address address1; private Address address2; ----private Address addressN; ----} In third case how to manage the records about addresses for that user, now for managing this type of problems we have to use the collection, we do not need to care about how many of the addresses user have. Lets see there are same change in the code for that...
class UserDetails{ ----private int userId; ----private List addresses = new ArrayList(); ----}
Hibernate provides the facility to persist the collections. A collection can be a list, set, map, collection, sorted set, sorted map. java.util.List, java.util.Set, java.util.Collection, java.util.SortedSet, java.util.SortedMap etc. are the real interface types to declared the persistent collection-value fields. Hibernate injects the persistent collections based on the type of interface. The collection instances usually behave likes the types of value behavior. Instances of collections are auto persisted if a persistent object refers it and are deleted automatically if it is not referred through. Elements of collection may shift from one table to another when a persistent object passed the collection to another persistent object.
We look following example of Object of Entity Type: @Entity @Table(name="TBL_USER_DETAILS") public class UserDetails{ @Id @Column(name="USER_ID", type="INTEGER") @GeneratedValue(strategy=GenerationType.AUTO) private long userId; @Column(name="USER_NAME", type="String") private String userName; @ElementCollection private Collection lisOfAddresses = new ArrayList(); public Collection getLisOfAddresses() { return lisOfAddresses; } public void setLisOfAddresses(Collection lisOfAddresses) { this.lisOfAddresses = lisOfAddresses; } 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; } public String toString() { return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]";
} }
@ElementCollection: Target: Fields (including property get methods) Defines a collection of instances of a basic type or embeddable class. Must be specified if the collection is to be mapped by means of a collection table.
Address.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable //for value object it is not is entity object. Value object means does not have real meaning for self individually. public class Address { @Column(name="STREET_NAME") private String street; @Column(name="CITY_NAME") private String city; @Column(name="STATE_NAME") private String state; @Column(name="PIN_CODE") private String pincode; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state;
} public void setState(String state) { this.state = state; } public String getPincode() { return pincode; } public void setPincode(String pincode) { this.pincode = pincode; } public String toString() { return " {Street: "+street+" City: "+city+" State: "+state+" Pincode: "+pincode+" }"; } } hibernate.cfg.xml will be the same as the previous chapter.
HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails();//Create user object user.setUserName("Dinesh Rajput"); //Set user name Address address1 = new Address(); // create first embedded object address address1.setStreet("First Street"); address1.setCity("First City"); address1.setState("First State"); address1.setPincode("First Pin");
Address address2 = new Address(); // create second embedded object address address2.setStreet("Second Street"); address2.setCity("Second City"); address2.setState("Second State"); address2.setPincode("Second Pin"); //adding addresses object to the list of address user.getLisOfAddresses().add(address1); user.getLisOfAddresses().add(address2); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create session factory object Session session = sessionFactory.openSession(); //create session object from the session factory session.beginTransaction(); //initialize the transaction object from session session.save(user); // save the user session.getTransaction().commit(); //commit the transaction session.close(); //closing session } } Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into TBL_USER_DETAILS (USER_NAME) values (?) Hibernate: insert into TBL_USER_DETAILS_lisOfAddresses (TBL_USER_DETAILS_USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: insert into TBL_USER_DETAILS_lisOfAddresses (TBL_USER_DETAILS_USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Look care fully to the output line, there are two tables here in the database, first for the UserDetails entity "TBL_USER_DETAILS" and second for the embeddable object Address name is "TBL_USER_DETAILS_lisOfAddresses " (this is default name of table for address Entity Table Name_field name of the list of the embeddable object in the entity class).
Here see that there is one table for the address object created separate for the collection. 1. First Table TBL_USER_DETAILS
2. Second Table TBL_USER_DETAILS_lisOfAddresses
In the second table first column TBL_USERS_DETAILS_USER_ID has the user id is foreign key for this table and primary key of the TBL_USER_DETAILS table.
Using Collections in Hibernate & Adding Keys : Chapter 15 In previous chapter we wrote the collection of objects of an entity class, we persist in the separate table, here there are following two tables are created in the database
1. TBL_USER_DETAILS for UserDetails entity type object 2. TBL_USER_DETAILS_lisOfAddresses for Address value type object
In this chapter we will explore some advanced options about the collection. Now we see first thing is the name of the table.
TBL_USER_DETAILS_lisOfAddresses is name for the collection table it is not very user friendly name.
To overcome this problem we will use annotation @JoinTable.
@JoinTable: Target: Fields (including property get methods) Used in the mapping of associations. It is specified on the owning side of an association. A join table is typically used in the mapping of many-to-many and unidirectional one-to-many associations. It may also be used to map bidirectional many-to-one/one-to-many associations, unidirectional many-to-one relationships, and one-to-one associations (both bidirectional and unidirectional). When a join table is used in mapping a relationship with an embeddable class on the owning side of the relationship, the containing entity rather than the embeddable class is considered the owner of the relationship. If the JoinTable annotation is missing, the default values of the annotation elements apply. The name of the join table is assumed to be the table names of the associated primary tables concatenated together (owning side first) using an underscore. @Entity @Table (name="USERS_DETAILS") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ElementCollection @JoinTable(name="USER_ADDRESS")//name of the table is changed to USER_ADDRESS private Collection lisOfAddresses = new ArrayList(); }
After running the above code the following output string show the updated table name of the collection table. Now we see that the name of the column of this table which have the foreign key user id is the USER_DETAILS_USER_ID is not also very user friendly, for this look to the following updated code of the UserDetails entity class. Here we used annotation@JoinColumn. @JoinColumn: Target:
Fields (including property get methods) Specifies a column for joining an entity association or element collection. If the JoinColumn annotation itself is defaulted, a single join column is assumed and the default values apply. @JoinColumns: Target: Fields (including property get methods) Defines mapping for composite foreign keys. This annotation groups JoinColumn annotations for the same relationship. When theJoinColumns annotation is used, both the name and the referencedColumnName elements must be specified in each suchJoinColumn annotation.
@Entity @Table (name="USERS_DETAILS") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ElementCollection @JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID")) private Collection lisOfAddresses = new ArrayList(); }
Look the following snap of the output..
Now we look for how to adding key to the collection table. UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection;
import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Table; import org.hibernate.annotations.CollectionId; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Type; @Entity @Table (name="USER_DETAIL") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ElementCollection @JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID")) @GenericGenerator(strategy="hilo", name = "hilo-gen") @CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "hilo-gen", type = @Type(type="long")) private Collection lisOfAddresses = new ArrayList(); public Collection getLisOfAddresses() { return lisOfAddresses; } public void setLisOfAddresses(Collection lisOfAddresses) { this.lisOfAddresses = lisOfAddresses; } 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; } public String toString() { return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]"; } }
Address.java and hibernate.cfg.xml is the same as previous chapter.
HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //user.setUserId(1); user.setUserName("Dinesh Rajput"); Address address1 = new Address(); address1.setStreet("First Street"); address1.setCity("First City"); address1.setState("First State"); address1.setPincode("First Pin"); Address address2 = new Address(); address2.setStreet("Second Street"); address2.setCity("Second City"); address2.setState("Second State"); address2.setPincode("Second Pin"); user.getLisOfAddresses().add(address1); user.getLisOfAddresses().add(address2);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); session.save(user); session.getTransaction().commit(); session.close(); } } Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAIL (USER_NAME) values (?) Hibernate: insert into USER_ADDRESS (USER_ID, ADDRESS_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?, ?) Hibernate: insert into USER_ADDRESS (USER_ID, ADDRESS_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?, ?)
Tables:
Proxy Objects and Eager & Lazy Fetch Types in Hibernate : Chapter 16 In this tutorial we look what is proxy object and how hibernate provide the proxy object for us and also we look about some fetching strategies.
So we first look about the proxy object. Hibernate Proxy Object: An object proxy is just a way to avoid retrieving an object until you need it.
In our example user class has the three field values1. User Id 2. User Name 3. List of the Addresses
If you want retrieve user object from the database, so what field value are retrieved from the database and which field are initialized. Suppose one user XYZ has the 100 addresses in the database and we want to retrieved the name of this user from database. For that we retrieve the user object, now question is this what about the field listOfAddress field, Is it also have the value? if you say yes so what about cost of memory ? if you say no so how to retrieve the value associated with that field the address table in the database on demand. -A | *---B | | | *---C | | | *---D | | | *---E | | | *---F | | | *---G *---H Ok lets see in the given below flow of the diagram.
In Hibernate 2 does not proxy objects by default. However, experience has shown that using object proxies is preferred, so this is the default in Hibernate 3.
In Hibernate 3, when we fetching the user object from the database actually its retrieved the proxy object of the user class means only first level of the fields are initializing with the associated values from the database. Field listOfAddresses does not have the value. If you want the list address you should call the following method you will get the listOfAddresses. user.getListOfAddress(); --->> this return the list of the address associated with that particular user which name is XYZ this is the default behavior of the Hibernate 3. Now we look about the fetching strategies. Fetching Strategies: there are two types of the fetching strategies in the hibernate. 1. Lazy Fetch type 2. Eager Fetch type LAZY = fetch when needed EAGER = fetch immediately
1. Lazy Fetch Type: This the default fetch type of the hibernate 3. Now when you load a User from the database, JPA loads its id, name, and address fields for you. But you have two options for users: to load it together with the rest of the fields (i.e. eagerly) or to load it ondemand (i.e. lazily) when you call the user'sgetListOfAddresses() method. Lazy/Select Fetch strategy:- Select Fetch strategy is the lazy fetching of associations. The purpose of Lazy strategy is memory optimization . When I say memory optimization it means it means it saves us
from heap error. This is what I think. So we can say yes if we are loading too objects in aseesion we should go for Lazy Fetch strategy but in terms of time performance it does not provide any Benefit. Agreed? When a user has many addresses it is not efficient to load all of its addresses with it when they are not needed. So in suchlike cases, you can declare that you want addresses to be loaded when they are actually needed. This is called lazy loading. EXAMPLE: UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Table; @Entity @Table (name="USER_DETAIL") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ElementCollection(fetch=FetchType.LAZY) @JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID")) private Collection lisOfAddresses = new ArrayList(); public Collection getLisOfAddresses() { return lisOfAddresses; } public void setLisOfAddresses(Collection lisOfAddresses) { this.lisOfAddresses = lisOfAddresses; } 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; } public String toString() { return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]"; } }
Now hibernate.cfg.xml and Address.java are same as the previous tutorial.
Now run the this with following class.
HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); // create user object //user.setUserId(1); user.setUserName("Dinesh Rajput"); Address address1 = new Address(); // create address object address1.setStreet("First Street"); address1.setCity("First City");
address1.setState("First State"); address1.setPincode("First Pin"); Address address2 = new Address(); // create another address object address2.setStreet("Second Street"); address2.setCity("Second City"); address2.setState("Second State"); address2.setPincode("Second Pin"); user.getLisOfAddresses().add(address1); // set the addresses objects to list of the addresses user.getLisOfAddresses().add(address2); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); // create session factory object Session session = sessionFactory.openSession(); // create session object session.beginTransaction(); // start transaction object session.save(user); // save the user to database session.getTransaction().commit(); // commit the transaction session.close(); // closing session session = sessionFactory.openSession(); // again create another session object user = null; user = (UserDetails) session.get(UserDetails.class, 1); // retrieved the user from the database for particular user which user id = 2 this object it is proxy user object. System.out.println(user.getLisOfAddresses().size()); } } ****************************************************************************** OUTPUT:Look care fully the output has the two select query one is for user and another is for address table when we callgetListOfAddresses();
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAIL (USER_NAME) values (?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_DETAIL userdetail0_ where userdetail0_.USER_ID=? Hibernate: select lisofaddre0_.USER_ID as USER1_0_, lisofaddre0_.CITY_NAME as CITY2_0_, lisofaddre0_.PIN_CODE as PIN3_0_, lisofaddre0_.STATE_NAME as STATE4_0_, lisofaddre0_.STREET_NAME as STREET5_0_ from USER_ADDRESS lisofaddre0_ where lisofaddre0_.USER_ID=? 2 ****************************************************************************** Now if you change to some lines of code for this class file to verify the PROXY object. Before calling getListOfAddresses() method close the session then look what happens.
session = sessionFactory.openSession(); // again create another session object user = null; user = (UserDetails) session.get(UserDetails.class, 1); // retrieved the user from the database for particular user which user id = 2 this object it is proxy user object. session.close(); // close the session before calling collection getter System.out.println(user.getLisOfAddresses().size()); Now Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAIL (USER_NAME) values (?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_DETAIL userdetail0_ where userdetail0_.USER_ID=? Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.sdnext.hibernate.tutorial.dto.UserDetails.lisOfAddresses, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException (AbstractPersistentCollection.java:380) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected (AbstractPersistentCollection.java:372) at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119) at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248) at com.sdnext.hibernate.tutorial.HibernateTestDemo.main(HibernateTestDemo.java:48) ****************************************************************************** As above code failed run because when we are using the LAZY Type strategy of fetching an object hibernate session return the proxy object, it exist in the session if we are closing the session the lazy loading is not happening.
2. Eager Fetch Strategy: In hibernate 2 this is default behavior of the to retrieving an object from the database. Eager/Join Fetch strategy:- Join Fetch strategy the eager fetching of associations.The purpose of Join Fetch strategy is optimization in terms of time.I mean even associations are fetched right at the time of fetching parent object. So in this case we don’t make database call again and again . So this will be much faster.Agreed that this will bad if we are fetching too many objects in a session because we can get java heap error.
Now we look on the code for EAGER LOADING. UserDetais.java package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection;
import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Table; @Entity @Table (name="USER_DETAIL") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ElementCollection(fetch=FetchType.EAGER) @JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID")) private Collection lisOfAddresses = new ArrayList(); public Collection getLisOfAddresses() { return lisOfAddresses; } public void setLisOfAddresses(Collection lisOfAddresses) { this.lisOfAddresses = lisOfAddresses; } 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; } public String toString() { return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]";
} }
Now run the following code and see the output--package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.Address; import com.sdnext.hibernate.tutorial.dto.UserDetails; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //user.setUserId(1); user.setUserName("Dinesh Rajput"); Address address1 = new Address(); address1.setStreet("First Street"); address1.setCity("First City"); address1.setState("First State"); address1.setPincode("First Pin"); Address address2 = new Address(); address2.setStreet("Second Street"); address2.setCity("Second City"); address2.setState("Second State"); address2.setPincode("Second Pin"); user.getLisOfAddresses().add(address1); user.getLisOfAddresses().add(address2); SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); session.save(user); session.getTransaction().commit(); session.close(); session = sessionFactory.openSession(); user = null;
user = (UserDetails) session.get(UserDetails.class, 1); session.close(); //closing the session before calling collection getter System.out.println(user.getLisOfAddresses().size()); } }
OUTPUT: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into USER_DETAIL (USER_NAME) values (?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?) Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_, lisofaddre1_.USER_ID as USER1_2_, lisofaddre1_.CITY_NAME as CITY2_2_, lisofaddre1_.PIN_CODE as PIN3_2_, lisofaddre1_.STATE_NAME as STATE4_2_, lisofaddre1_.STREET_NAME as STREET5_2_ from USER_DETAIL userdetail0_ left outer join USER_ADDRESS lisofaddre1_ on userdetail0_.USER_ID=lisofaddre1_.USER_ID where userdetail0_.USER_ID=? 2****************************************************************************** See this is successfully run the code because we are using the EAGER fetching strategy so in this strategy session return the original object with all field are initialized when load on the memory. In the above output string look care fully there are only one select statement with join clause.
So now can we say in the hibernate session where we are not loading too many objects we should go for Eager fetch as it will be much better in terms of time response(Any ways memory will be reclaimed by garbage collector once we close the session).
Hibernate One-To-One Mapping Tutorial : Chapter 17 In the previous chapter we learned about the entity class has the field of the value type object and also has the collection of thevalue type objects. Now we will learning what happens when an entity class has the field of the entity type object. Means that one entity is inside the one entity known as One-2-One Mapping.
Hibernate Mapping One-to-One:In this example you will learn how to map one-to-one relationship using Hibernate. Consider the following relationship between UserDetails and Vehicle entity.
According to the relationship each user should have a unique vehicle.
For that we will use the following annotation. @OneToOne: Target:
Fields (including property get methods) Defines a single-valued association to another entity that has one-to-one multiplicity. It is not normally necessary to specify the associated target entity explicitly since it can usually be inferred from the type of the object being referenced. If the relationship is bidirectional, the non-owning side must use the mappedBy element of the @OneToOne annotation to specify the relationship field or property of the owning side. The @OneToOne annotation may be used within an embeddable class to specify a relationship from the embeddable class to an entity class. Now we look the following Example related to the One to One mapping. 1. First Create Vehicle Class Vehicle.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="VEHICLE") public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") 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;
} } 2. Create the User Class UserDetails.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table (name="USER_DETAIL") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @OneToOne @JoinColumn(name="VEHICLE_ID") private Vehicle vehicle; public Vehicle getVehicle() { return vehicle; } public void setVehicle(Vehicle vehicle) { this.vehicle = vehicle; } 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; } }
3. Create the hibernate configuration file. hibernate.cfg.xml:
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB root root 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
4. Create Test Demo class for run this code. HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; import com.sdnext.hibernate.tutorial.dto.Vehicle; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //create the user entity Vehicle vehicle = new Vehicle(); //create the vehicle entity vehicle.setVehicleName("BMW Car"); //set vehicle name user.setUserName("Dinesh Rajput"); //set the user name user.setVehicle(vehicle); //set the vehicle entity to the field of the user entity i.e. vehicle entity inside the user entity SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create session factory object Session session = sessionFactory.openSession(); //create the session object session.beginTransaction();//create the transaction from the session object session.save(vehicle); // save the vehicle entity to the database session.save(user); // save the user entity to the database session.getTransaction().commit(); //close the transaction session.close(); //close the session } } OUTPUT: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into VEHICLE (VEHICLE_NAME) values (?) Hibernate: insert into USER (USER_NAME, VEHICLE_ID) values (?, ?)
Now we look the created tables for that.
One-To-Many Mapping in Hibernate : Chapter 18 In this chapter we will discuss about the One To Many Mapping. In previous we look that what is One To One Mapping and also discussed some examples about that. A one-to-many relationship occurs when one entity is related to many occurrences in another entity.
In this chapter you will learn how to map one-to-many relationship using Hibernate. Consider the following relationship betweenUserDetails Class and Vehicle entity.
One user have the multiple vehicles.
Class diagram for that given below.
In this example UserDetails class has the collection of the another entity class Vehicle. So the given below diagram so table structure for that.
For that we will use the following annotation. @OneToMany: Target:
Fields (including property get methods) Defines a many-valued association with one-to-many multiplicity. If the collection is defined using generics to specify the element type, the associated target entity type need not be specified; otherwise the target entity class must be specified. If the relationship is bidirectional, the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship. The OneToMany annotation may be used within an embeddable class contained within an entity class to specify a relationship to a collection of entities. If the relationship is bidirectional, the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship. Now we look the following Example related to the One to Many mapping. 1. First Create Vehicle Class Vehicle.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="VEHICLE") public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") 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; } } 2. Create the User Class UserDetails.java package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table (name="USER") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @OneToMany @JoinTable( name="USER_VEHICLE", joinColumns=@JoinColumn(name="USER_ID"), inverseJoinColumns=@JoinColumn(name="VEHICLE_ID")) //its optional using for name configuration of the join table private Collection vehicle = new ArrayList(); public int getUserId() { return userId; } public Collection getVehicle() { return vehicle; } public void setVehicle(Collection vehicle) { this.vehicle = vehicle;
} public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
3. Create the hibernate configuration file. hibernate.cfg.xml:
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB root root 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
4. Create Test Demo class for run this code. HibernateTestDemo.java package com.sdnext.hibernate.tutorial;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails; import com.sdnext.hibernate.tutorial.dto.Vehicle;
public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //create the user entity object Vehicle vehicle = new Vehicle(); //create the first vehicle entity object Vehicle vehicle2 = new Vehicle(); //create the second vehicle entity vehicle.setVehicleName("BMW Car"); //set the value to the vehicle entity vehicle2.setVehicleName("AUDI Car"); user.setUserName("Dinesh Rajput"); //Set the value to the user entity user.getVehicle().add(vehicle); //add vehicle to the list of the vehicle user.getVehicle().add(vehicle2);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create session factory object Session session = sessionFactory.openSession(); //create the session object session.beginTransaction(); //start the transaction of the session object session.save(vehicle); //saving the vehicle to the database session.save(vehicle2); session.save(user); //save the user to the database session.getTransaction().commit(); //close the transaction session.close(); //close the session } } ****************************************************************************** OUTPUT: ****************************************************************************** log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into VEHICLES (VEHICLE_NAME) values (?) Hibernate: insert into VEHICLES (VEHICLE_NAME) values (?) Hibernate: insert into USER (USER_NAME) values (?) Hibernate: insert into USER_VEHICLE (USER_ID, VEHICLE_ID) values (?, ?) Hibernate: insert into USER_VEHICLE (USER_ID, VEHICLE_ID) values (?, ?)
Now we look the table structure about this example.
Now how can implement this mapping through mapping file( .hbm.xml) instead of the annotations. For user class.. UserDetails.hbm.xml
Mapping File For Vehicle Class... vehicle.hbm.xml
So it is brief description about the One To Many Mapping with using annotation and also using .hbm.xml files for entity class.
Many-To-One Mapping in Hibernate : Chapter 19 In this chapter we will discuss about the Many To One Relationship Mapping. In previous we look that what is One To Many Mapping and also discussed some examples about that. Actually Many To One is the reverse of the One To Many(USER has many Vehicles means one user related to the many vehicles in reverse we can say that many vehicles related to the one user i.e. Many To One relationship mapping).
Many-to-One Relationships: A many-to-one relationship is where one entity contains values that refer to another entity (a column or set of columns) that has unique values. In relational databases, these many-to-one relationships are often enforced by foreign key/primary key relationships, and the relationships typically are between fact and dimension tables and between levels in a hierarchy.
In this example multiple vehicles (BMW Car, AUDI Car, Maruti Car and Mahindra etc.) are linked to the same User (whose primary key is 1).
Class diagram for that is given below.
According to the relationship many vehicles can have the same owner.
To create this relationship you need to have a USER and VEHICLE table. The relational model is shown below.
For that we will use the following annotation. @ManyToOne : Target: Fields (including property get methods) Defines a single-valued association to another entity class that has many-to-one multiplicity. It is not normally necessary to specify the target entity explicitly since it can usually be inferred from the type of the object being referenced. If the relationship is bidirectional, the nonowning OneToMany entity side must used the mappedBy element to specify the relationship field or property of the entity that is the owner of the relationship. The ManyToOne annotation may be used within an embeddable class to specify a relationship from the embeddable class to an entity class. If the relationship is bidirectional, the nonowning OneToMany entity side must use the mappedByelement of the OneToMany annotation to specify the relationship field or property of the embeddable field or property on the owning side of the relationship. The dot (".") notation syntax must be used in the mappedBy element to indicate the relationship attribute within the embedded attribute. The value of each identifier used with the dot notation is the name of the respective embedded field or property.
Now we look the following Example related to the One to Many mapping. UserDetails.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table (name="USER") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @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; } } Vehicle.java package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="VEHICLE") public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") private String vehicleName; @ManyToOne @JoinColumn(name ="USER_ID") private UserDetails user; public UserDetails getUser() { return user; } public void setUser(UserDetails user) { this.user = user; } 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; } }
hibernate.cfg.xml:
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernateDB root root 1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true create
HibernateTestDemo.java package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; import com.sdnext.hibernate.tutorial.dto.Vehicle; public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); //create an user entity Vehicle vehicle = new Vehicle(); //create a vehicle entity Vehicle vehicle2 = new Vehicle(); //create second vehicle entity vehicle.setVehicleName("BMW Car"); //set BMW car vehicle.setUser(user); //set user for that car vehicle2.setVehicleName("AUDI Car"); //set second car Audi vehicle2.setUser(user);//set user for that car user.setUserName("Dinesh Rajput"); //set user property SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); //create the session factory object Session session = sessionFactory.openSession(); //create the session object session.beginTransaction(); //create the transaction object session.save(vehicle); session.save(vehicle2); session.save(user); session.getTransaction().commit(); session.close(); } } ****************************************************************************** OUTPUT: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly. Hibernate: insert into VEHICLE (USER_ID, VEHICLE_NAME) values (?, ?) Hibernate: insert into VEHICLE (USER_ID, VEHICLE_NAME) values (?, ?) Hibernate: insert into USER (USER_NAME) values (?) Hibernate: update VEHICLE set USER_ID=?, VEHICLE_NAME=? where VEHICLE_ID=? Hibernate: update VEHICLE set USER_ID=?, VEHICLE_NAME=? where VEHICLE_ID=?
Now we look the table structure about this example.
Now how can implement this mapping through mapping file( .hbm.xml) instead of the annotations. For user class.. UserDetails.hbm.xml
Mapping File For Vehicle Class... vehicle.hbm.xml
The many-to-one element is used to create the many-to-one relationship between the Vehicle and UserDetail entities. The cascadeoption is used to cascade the required operations to the associated entity. If the cascade option is set to all then all the operations will be cascaded. For instance when you save a Vehicle object, the associated UserDetail object will also be saved automatically.
In Next Chapter we will discuss about the Many To Many Mapping.
Many-To-Many Mapping in Hibernate : Chapter 20 Many-to-many relationships occur when each record in an entity may have many linked records in another entity and vice-versa. In this chapter you will learn how to map many-to-many relationship using Hibernate. Consider the following relationship betweenVehicle and UserDetails entity.
According to the relationship a user can have in any number of vehicles and the vehicle can have any number of users. UserDetail.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46.
package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection; import import import import import import import
javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.ManyToMany; javax.persistence.Table;
@Entity @Table (name="USER") public class UserDetails { @Id @Column(name="USER_ID") @GeneratedValue(strategy=GenerationType.AUTO) private int userId; @Column(name="USER_NAME") private String userName; @ManyToMany private Collection vehicle = new ArrayList(); public int getUserId() { return userId; } public Collection getVehicle() { return vehicle; } public void setVehicle(Collection vehicle) { this.vehicle = vehicle; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; }
47.
}
Vehicle.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47.
package com.sdnext.hibernate.tutorial.dto; import java.util.ArrayList; import java.util.Collection; import import import import import import import
@Entity @Table(name="VEHICLE") public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") private String vehicleName; @ManyToMany(mappedBy="vehicle") private Collection user = new ArrayList(); public Collection getUser() { return user; } public void setUser(Collection user) { this.user = user; } 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; } }
hibernate.cfg.xml: view plainprint?
javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.ManyToMany; javax.persistence.Table;
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/hibernateDB 6. root 7. root 8. 9. 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvid er 20. 21. 22. true 23. 24. 25. create 26. 27. 28. 29. 30. 31. 32.
HibernateTestDemo.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.UserDetails; import com.sdnext.hibernate.tutorial.dto.Vehicle;
public class HibernateTestDemo { /** * @param args */ public static void main(String[] args) { UserDetails user = new UserDetails(); UserDetails user2 = new UserDetails(); Vehicle vehicle = new Vehicle();
22. Vehicle vehicle2 = new Vehicle(); 23. 24. vehicle.setVehicleName("Car"); 25. vehicle.getUser().add(user); 26. vehicle.getUser().add(user2); 27. 28. vehicle2.setVehicleName("Jeep"); 29. vehicle2.getUser().add(user2); 30. vehicle2.getUser().add(user); 31. 32. user.setUserName("First User"); 33. user2.setUserName("Second User"); 34. user.getVehicle().add(vehicle); 35. user.getVehicle().add(vehicle2); 36. user2.getVehicle().add(vehicle); 37. user2.getVehicle().add(vehicle2); 38. 39. SessionFactory sessionFactory = new AnnotationConfiguration().configure( ).buildSessionFactory(); 40. Session session = sessionFactory.openSession(); 41. session.beginTransaction(); 42. session.save(vehicle); 43. session.save(vehicle2); 44. session.save(user); 45. session.save(user2); 46. session.getTransaction().commit(); 47. session.close(); 48. } 49. }
Using Mapping files instead of Annotation userDetail.hbm.xml view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
vehicle.hbm.xml view plainprint?
1. 2. 3. 4. 5. 6. 7. 8.
CascadeTypes in Hibernate and Other Things : Chapter 21 In this section, you will know about the jpa relationship. JPA supports the relationship between entities.
JPA Relationship In this section, you will know about the jpa relationship. JPA supports the relationship between entities. There are following types of relationship: 1. One-to-one 2. One-to-many 3. Many-to-one 4. Many-to-many JPA relationships are not bi-directional. JPA annotations are added to define the relationship. If, you want to make a relationship bi-directional to use a special attribute. 1. One-to-one: A OneToOne relation mapping to a single-value association to another entity. It has one-to-one multiplicity and infers the associated target entity from the type of the object being referenced. Use of the @OneToOne Annotation: 1. Configure the fetch type to LAZY 2. Configure the mapping to forbid null values (for non-primitive types) in case null values are inappropriate for your application 3. Configure the associated target entity if it cannot be inferred from the type of the object being referenced 4. Configure the operations that must be cascaded to the target of the association. For example, if the owning entity is removed, ensure that the target of the association is also removed 2. One-to-many: JPA defines a OneToMany mapping for a many-valued association with one-to-many multiplicity. Use of the @OneToMany Annotation: 1. Configure the fetch type to EAGER 2. Configure the associated target entity because the Collection used is not defined using generics 3. Configure the operations that must be cascaded to the target of the association: for example, if the owning entity is removed, ensure that the target of the association is also removed 4. Configure the details of the join table used by TopLink JPA for uni-directional one-to-many relationships 3. Many-to-one: JPA defines a ManyToOne mapping for a single-valued association to another entity class that has many-to-one multiplicity. Use the @ManyToOne Annotation to: 1. Configure the fetch type to LAZY 2. Configure the mapping to forbid null values (for non-primitive types) in case null values are inappropriate for your application
3. Configure the associated target entity if it cannot be inferred from the type of the object being referenced 4. Configure the operations that must be cascaded to the target of the association: for example, if the owning entity is removed, ensure that the target of the association is also removed 4. Many-to-many: JPA defines a @ManyToMany mapping for a many-valued association with many-to-many multiplicity. Use of the @ManyToMany annotation: 1. Declare the cardinality of the relationship 2. Configure the fetch type to EAGER 3. Configure the mapping to forbid null values (for non-primitive types) in case null values are inappropriate for your application 4. Configure the associated target entity because the Collection used is not defined using generics 5. Configure the operations that must be cascaded to the target of the association; for example, if the owning entity is removed, ensure that the target of the association is also removed There are following types of cascade: 6. CascadeType.PERSIST: When we persist and entity all the entities held in this field persist too. If you want to persist an entity and the fields dont use it fails. 7. CascadeType.REMOVE: When we delete an entity all the entities held in this field delete too. 8. CascadeType.REFRESH: When we refresh an entity all the entities held in this field refresh too. 9. CascadeType.MERGE: When we merde an entity all the entities held in this flied merged too The property cascade = CascadeType.ALL indicates that when we persist, remove, refresh or merge this entity all the entities held in this field would be persist, remove, delete or update.
Implementing Inheritance in Hibernate (Single Table Strategy, With Table Per Class Strategy, With Joined Strategy) : Chapter 22 This tutorial discusses what are the types of inheritance models in Hibernate and describes how they work like vertical inheritance and horizontal. There are three types of inheritance mapping in hibernate 1. Table per concrete class with unions 2. Table per class hierarchy(Single Table Strategy) 3. Table per subclass Example: Let us take the simple example of 3 java classes. Class TwoWheelerVehicle and FourWheelerVehicle are inherited from Vehicle Abstract class.
1. Table per concrete class with unions In this case there will be 2 tables Tables: TwoWheelerVehicle, FourWheelerVehicle[all common attributes will be duplicated] 2. Table per class hierarchy Single Table can be mapped to a class hierarchy There will be only one table in database called 'Vehicle' that will represent all the attributes required for all 3 classes. But it needs some discriminating column to differentiate between TwoWheelerVehicle and FourWheelerVehicle; 3. Table per subclass In this case there will be 3 tables represent TwoWheelerVehicle , FourWheelerVehicle and Vehicle
Inheritance is one of the most visible facets of Object-relational mismatch. Object oriented systems can model both “is a” and “has a” relationship. Relational model supports only “has a” relationship between two entities. Hibernate can help you map such Objects with relational tables. But you need to choose certain mapping strategy based on your needs. There are three possible strategies to use.
1. 2.
Single Table Strategy, With Table Per Class Strategy,
3.
With Joined Strategy
Single Table Strategy In Single table per subclass, the union of all the properties from the inheritance hierarchy is mapped to one table. As all the data goes in one table, a discriminator is used to differentiate between different type of data. Advantages of Single Table per class hierarchy
Simplest to implement.
Only one table to deal with.
Performance wise better than all strategies because no joins or sub-selects need to be performed. Disadvantages: Most of the column of table are nullable so the NOT NULL constraint cannot be applied. Tables are not normalized. Lets see the following example code. Vehicle.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. gy 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33.
package com.sdnext.hibernate.tutorial.dto; import import import import import import import import
javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.Inheritance; javax.persistence.InheritanceType; javax.persistence.Table;
@Entity @Table(name="VEHICLE") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) //Least normalisation strate public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") private String vehicleName; public int getVehicleId() { return vehicleId; } public void setVehicleId(int vehicleId) { this.vehicleId = vehicleId; } public String getVehicleName() { return vehicleName; }
34. 35. 36. 37.
public void setVehicleName(String vehicleName) { this.vehicleName = vehicleName; } }
TwoWheeler.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name="TWO_WHEELER") //@DiscriminatorValue("Bike") public class TwoWheeler extends Vehicle { @Column(name="STEERING_TYPE") private String steeringTwoWheeler; public String getSteeringTwoWheeler() { return steeringTwoWheeler; } public void setSteeringTwoWheeler(String steeringTwoWheeler) { this.steeringTwoWheeler = steeringTwoWheeler; } }
FourWheeler.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name="FOUR_WHEELER") //@DiscriminatorValue("Car") public class FourWheeler extends Vehicle { @Column(name="STEERING_TYPE") private String steeringFourWheeler; public String getSteeringFourWheeler() { return steeringFourWheeler; } public void setSteeringFourWheeler(String steeringFourWheeler) { this.steeringFourWheeler = steeringFourWheeler;
23. 24.
} }
hibernate.cfg.xml view plainprint?
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/vehicleDB2 6. root 7. root 8. 9. 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. create 26. 27. 28. 29. 30. 31. 32. 33.
Now run the following test class HibernateTestDemo.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import com.sdnext.hibernate.tutorial.dto.FourWheeler; import com.sdnext.hibernate.tutorial.dto.TwoWheeler; import com.sdnext.hibernate.tutorial.dto.Vehicle; public class HibernateTestDemo { /**
14. * @param args 15. */ 16. public static void main(String[] args) 17. { 18. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil dSessionFactory(); 19. Session session = sessionFactory.openSession(); 20. session.beginTransaction(); 21. 22. Vehicle vehicle = new Vehicle(); 23. vehicle.setVehicleName("Car"); 24. 25. TwoWheeler twoWheeler = new TwoWheeler(); 26. twoWheeler.setVehicleName("Bike"); 27. twoWheeler.setSteeringTwoWheeler("Bike Steering Handle"); 28. 29. FourWheeler fourWheeler = new FourWheeler(); 30. fourWheeler.setVehicleName("Alto"); 31. fourWheeler.setSteeringFourWheeler("Alto Steering Wheel"); 32. 33. session.save(vehicle); 34. session.save(twoWheeler); 35. session.save(fourWheeler); 36. 37. session.getTransaction().commit(); 38. session.close(); 39. } 40. }
In the above table Vehicle there are four columns (DTYPE, VEHICLE_ID, VEHICLE_NAME, STEERING_TYPE). The first column has the value of discriminator type(DTYPE) is Vehicle, TwoWheeler, FourWheeler as its entity name by default. For user convenience we can override the default value of column as well as column name by using the following annotation.
@DiscriminatorColumn Target: Classes Specifies the discriminator column for the SINGLE_TABLE and JOINED Inheritance mapping strategies. The strategy and the discriminator column are only specified in the root of an entity class hierarchy or subhierarchy in which a different inheritance strategy is applied If the DiscriminatorColumn annotation is missing, and a discriminator column is required, the name of the discriminator column defaults to "DTYPE" and the discriminator type to DiscriminatorType.STRING. @DiscriminatorValue Target: Classes Specifies the value of the discriminator column for entities of the given type. The DiscriminatorValue annotation can only be specified on a concrete entity class. If the DiscriminatorValue annotation is not specified and a discriminator column is used, a providerspecific function will be used to generate a value representing the entity type. If the DiscriminatorType is STRING, the discriminator value default is the entity name. The inheritance strategy and the discriminator column are only specified in the root of an entity class hierarchy or subhierarchy in which a different inheritance strategy is applied. The discriminator value, if not defaulted, should be specified for each entity class in the hierarchy. @Inheritance Target: Classes Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy. If the Inheritance annotation is not specified or if no inheritance type is specified for an entity class hierarchy, the SINGLE_TABLE mapping strategy is used. Now adding the following annotation to the Vehicle class is view plainprint?
1. 2. 3. gy 4. 5. 6. 7. 8. 9.
@Entity @Table(name="VEHICLE") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) //Least normalisation strate @DiscriminatorColumn( name="VEHICLE_TYPE", discriminatorType=DiscriminatorType.STRING ) public class Vehicle {
Now adding following annotation to the TwoWheeler class view plainprint?
1. 2. 3.
@DiscriminatorValue("Bike") public class TwoWheeler extends Vehicle {
Now adding following annotation to the FourWheeler class view plainprint?
1. 2. 3.
@DiscriminatorValue("Car") public class FourWheeler extends Vehicle {
After these above modification we run the code then we will get the following output.
With Table Per Class Strategy In this case every entity class has its own table i.e. table per class. The data for Vehicle is duplicated in both the tables. This strategy is not popular and also have been made optional in Java Persistence API. Advantage:
Possible to define NOT NULL constraints on the table.
Disadvantage:
Tables are not normalized.
To support polymorphism either container has to do multiple trips to database or use SQL UNION kind of feature. In this case there no need for the discriminator column because all entity has own table. The Vehicle entity in this case is Vehicle.java view plainprint?
1. 2. 3. 4. 5.
package com.sdnext.hibernate.tutorial.dto; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType;
6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. d 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39.
import import import import import import import
javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.Inheritance; javax.persistence.InheritanceType; javax.persistence.Table;
@Entity @Table(name="VEHICLE") @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) //slightly more normalize public class Vehicle { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") 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; } }
And there no need to the discriminator value for the TwoWheeler and FourWheeler Entity so in this case the TwoWheeler.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
package com.sdnext.hibernate.tutorial.dto; import import import import
javax.persistence.Column; javax.persistence.DiscriminatorValue; javax.persistence.Entity; javax.persistence.Table;
@Entity @Table(name="TWO_WHEELER") public class TwoWheeler extends Vehicle { @Column(name="STEERING_TYPE") private String steeringTwoWheeler; public String getSteeringTwoWheeler() { return steeringTwoWheeler; } public void setSteeringTwoWheeler(String steeringTwoWheeler)
21. 22. 23. 24.
{ this.steeringTwoWheeler = steeringTwoWheeler; } }
FourWheeler.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
package com.sdnext.hibernate.tutorial.dto; import import import import
javax.persistence.Column; javax.persistence.DiscriminatorValue; javax.persistence.Entity; javax.persistence.Table;
@Entity @Table(name="FOUR_WHEELER") public class FourWheeler extends Vehicle { @Column(name="STEERING_TYPE") private String steeringFourWheeler; public String getSteeringFourWheeler() { return steeringFourWheeler; } public void setSteeringFourWheeler(String steeringFourWheeler) { this.steeringFourWheeler = steeringFourWheeler; } }
With Joined Strategy It's highly normalized but performance is not good. Advantage:
Tables are normalized.
Able to define NOT NULL constraint. Disadvantage: Does not perform as well as SINGLE_TABLE strategy Using Join Strategy with the vehicle entity Vehicle.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39.
package com.sdnext.hibernate.tutorial.dto; import import import import import import import import import import
javax.persistence.Column; javax.persistence.DiscriminatorColumn; javax.persistence.DiscriminatorType; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.Inheritance; javax.persistence.InheritanceType; javax.persistence.Table;
@Entity @Table(name="VEHICLE") @Inheritance(strategy=InheritanceType.JOINED)//Highly normalized public class Vehicle { @Id @GeneratedValue @Column(name="VEHICLE_ID") private int vehicleId; @Column(name="VEHICLE_NAME") 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; } }
Now run the code we will get the following output.
We have seen the three strategies about inheritance in the hibernate. A comparison of three strategies is as follows:
Criteria
Single Table
Table per subclass(Join Strategy)
Data not normalized. Constraint for Normalized. mandatory columns to be Table Support not nullable cannot Mandatory column constraint applied. can be applied Change in any subclass leads to change in structure of Table Discriminator Present Column
Retrieving data
simple SELECT. All data is in one table. Using discriminator type, individual types can be selected
Absent
Table per Class
One table for each concrete class. Not maintainable. Change in base class leads to changes in all tables of derived class Absent
Joins among table. For example fetching FourWheeler will require a Separate Select or join on FourWheeler and Vehicle table. Union Select If all user needs to be fetched than it will put a join for all three tables
Multiple. For Vehicle type one insert Updating and Single INSERT or UPDATE on Vehicle table. For FourWheeler Inserting type one insert on Vehicle table and
One insert or update for each subclass
another on FourWheeler table. JPA Support
Mandatory
Optional
CRUD Operations Using Hibernate 3 (Annotation and Configuration) : Chapter 23 In this section, you will learn how to develop a CRUD application using hibernate annotation. Follows the following steps for developing the CRUD application in hibernate annotation. Step 1: Create Domain Entity Class Student.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42.
package com.sdnext.hibernate.tutorial.dto; import java.io.Serializable; import import import import
javax.persistence.Column; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id;
@Entity @Table(name="STUDENT") public class Student implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 8633415090390966715L; @Id @Column(name="ID") @GeneratedValue(strategy=GenerationType.AUTO) private int id; @Column(name="STUDENT_NAME") private String studentName; @Column(name="ROLL_NUMBER") private int rollNumber; @Column(name="COURSE") private String course; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public int getRollNumber() { return rollNumber;
43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53.
} public void setRollNumber(int rollNumber) { this.rollNumber = rollNumber; } public String getCourse() { return course; } public void setCourse(String course) { this.course = course; } }
Step 2: Create Hibernate Configuration file hibernate.cfg.xml file contains (a.) database connection setting (database driver (com.mysql.jdbc.Driver), url (jdbc:mysql://localhost:3306/hibernateDB2), username (root) and password (root)), (b.) SQL dialect (dialect - org.hibernate.dialect.MySQLDialect), (c.) enable hibernate's automatic session context management (current_session_context_class thread), (d.) disable the second level cache (cache.provider_class - org.hibernate.cache.NoCacheProvider), (e.) print all executed SQL to stdout (show_sql - true) and (f.) drop and re-create the database schema on startup (hbm2ddl.auto - none). view plainprint?
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/hibernateDB2 6. root 7. root 8. 9. 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. update 26. 27. 28. 29. 30.
Step 3: Create Hibernate Utility Class HibernateUtil.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. y(); 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
package com.sdnext.hibernate.tutorial.utility; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { sessionFactory = new AnnotationConfiguration().configure().buildSessionFactor } catch(Throwable th){ System.err.println("Enitial SessionFactory creation failed"+th); throw new ExceptionInInitializerError(th); } } public static SessionFactory getSessionFactory(){ return sessionFactory; } }
Step 4: Create Student on the database. CreateStudent.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.sdnext.hibernate.tutorial.dto.Student; import com.sdnext.hibernate.tutorial.utility.HibernateUtil; public class CreateStudent { /** * @param args */ public static void main(String[] args) { //Create student entity object Student student = new Student(); student.setStudentName("Dinesh Rajput"); student.setRollNumber(01); student.setCourse("MCA"); //Create session factory object SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //getting session object from session factory Session session = sessionFactory.openSession(); //getting transaction object from session object session.beginTransaction(); session.save(student); System.out.println("Inserted Successfully");
31. 32. 33. 34. 35.
session.getTransaction().commit(); session.close(); sessionFactory.close(); } }
OUTPUT: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?) Inserted Successfully
Now the following code the reading the student data from database. Step 5: Reading the Student data from the database table STUDENT ReadStudent.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
package com.sdnext.hibernate.tutorial; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.sdnext.hibernate.tutorial.dto.Student; import com.sdnext.hibernate.tutorial.utility.HibernateUtil; public class ReadStudent { /** * @param args */ public static void main(String[] args) { //Create session factory object SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //getting session object from session factory Session session = sessionFactory.openSession(); //getting transaction object from session object session.beginTransaction(); Query query = session.createQuery("from Student"); List students = query.list();
27. for(Student student : students) 28. { 29. System.out.println("Roll Number: "+student.getRollNumber()+", Student Name: "+st udent.getStudentName()+", Course: "+student.getCourse()); 30. } 31. session.getTransaction().commit(); 32. sessionFactory.close(); 33. } 34. } 35.
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_, student0_.ROLL_NUMBER as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from STUDENT student0_ Roll Number: 1, Student Name: Dinesh Rajput, Course: MCA Roll Number: 2, Student Name: Anamika Rajput, Course: PGDCP Roll Number: 3, Student Name: Adesh Rajput, Course: MA Roll Number: 4, Student Name: Vinesh Rajput, Course: BA
The following code is for updating the data into the database table "STUDENT". Step 6: Update the Student Record in the Database. UpdateStudent.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.sdnext.hibernate.tutorial.dto.Student; import com.sdnext.hibernate.tutorial.utility.HibernateUtil; public class UpdateStudent { /** * @param args */ public static void main(String[] args) { //Create session factory object SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //getting session object from session factory Session session = sessionFactory.openSession(); //getting transaction object from session object session.beginTransaction(); Student student = (Student)session.get(Student.class, 2); student.setStudentName("Sweety Rajput");
25. 26. 27. 28. 29.
System.out.println("Updated Successfully"); session.getTransaction().commit(); sessionFactory.close(); } }
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select student0_.ID as ID0_0_, student0_.COURSE as COURSE0_0_, student0_.ROLL_NUMBER as ROLL3_0_0_, student0_.STUDENT_NAME as STUDENT4_0_0_ from STUDENT student0_ where student0_.ID=? Hibernate: update STUDENT set COURSE=?, ROLL_NUMBER=?, STUDENT_NAME=? where ID=? Updated Successfully
Step 7: Delete the student data from the database. DeleteStudent.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.sdnext.hibernate.tutorial.dto.Student; import com.sdnext.hibernate.tutorial.utility.HibernateUtil; public class DeleteStudent { /** * @param args */ public static void main(String[] args) { //Create session factory object SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //getting session object from session factory Session session = sessionFactory.openSession(); //getting transaction object from session object session.beginTransaction();
22. 23. 24. 25. 26. 27. 28.
Student student = (Student)session.load(Student.class, 4); session.delete(student); System.out.println("Deleted Successfully"); session.getTransaction().commit(); sessionFactory.close(); } }
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select student0_.ID as ID0_0_, student0_.COURSE as COURSE0_0_, student0_.ROLL_NUMBER as ROLL3_0_0_, student0_.STUDENT_NAME as STUDENT4_0_0_ from STUDENT student0_ where student0_.ID=? Deleted Successfully Hibernate: delete from STUDENT where ID=?
Transient, Persistent and Detached Objects in Hibernate : Chapter 24 In couple of previous chapters we have seen that every entity object are passed to three states of the object before saving and updating the row in the database table as per as given in the following picture.
1. Transient State: A New instance of a persistent class which is not associated with a Session, has no representation in the database and no identifier value is considered transient by Hibernate: view plainprint?
1. 2.
UserDetail user = new UserDetail(); user.setUserName("Dinesh Rajput");
3.
// user is in a transient state
2. Persistent State: A persistent instance has a representation in the database , an identifier value and is associated with a Session. You can make a transient instance persistent by associating it with a Session: view plainprint?
1. 2.
Long id = (Long) session.save(user); // user is now in a persistent state
3. Detached State: Now, if we close the Hibernate Session, the persistent instance will become a detached instance: it isn't attached to aSession anymore (but can still be modified and reattached to a new Session later though). view plainprint?
1. 2.
session.close(); //user in detached state
Difference between Transient and Detached States: Transient objects do not have association with the databases and session objects. They are simple objects and not persisted to the database. Once the last reference is lost, that means the object itself is lost. And of course , garbage collected. The commits and rollbacks will have no effects on these objects. They can become into persistent objects through the save method calls of Session object. The detached object have corresponding entries in the database. These are persistent and not connected to the Session object. These objects have the synchronized data with the database when the session was closed. Since then, the change may be done in the database which makes this object stale. The detached object can be reattached after certain time to another object in order to become persistent again. Lets see in the following example to save or update the user data... view plainprint?
1. package com.sdnext.hibernate.tutorial; 2. 3. import org.hibernate.Session; 4. import org.hibernate.SessionFactory; 5. import org.hibernate.cfg.AnnotationConfiguration; 6. 7. import com.sdnext.hibernate.tutorial.dto.UserDetails; 8. 9. public class HibernateTestDemo { 10. /** 11. * @param args 12. */ 13. public static void main(String[] args) 14. { 15. UserDetails userDetails = new UserDetails(); 16. userDetails.setUserName("Dinesh Rajput"); 17. userDetails.setAddress("Noida City"); 18. //Here 'userDetails' is TRANSIENT object 19. 20. SessionFactory sessionFactory = new AnnotationConfiguration().co nfigure().buildSessionFactory(); 21. Session session = sessionFactory.openSession(); 22. session.beginTransaction(); 23. 24. session.save(userDetails); 25. //Here 'userDetails' is PERSISTENT object 26. userDetails.setUserName("User Updated after session close"); 27. 28. session.getTransaction().commit();
29. 30. 31. 32.
session.close(); //Here 'userDetails' is DETACHED object } }
State Changes of Object in Hibernate : Chapter 25 In the previous tutorial you learned about the three states of the entity object using by the Hibernate API. 1. Transient State 2. Persistent State 3. Detached State Now you will learn how to flow of object in these states and how to manage by the hibernate.Look in the following figures-
1. When Creating a new Entity Object
Here we see when create an object it is in transient state in this state hibernate does not ask for save this object means that in this state hibernate's session does not associate with that object in this state. Once we calling session's save method now object move to the persistent state i.e. hibernate's session associated with that object in this state if any change made in the object hibernate ask to the database and made change in the database also. After done our required events when we calling session's close method then object moves in the detached state.
2. When Reading an Entity Object
Here we see that we are not getting new object from new operator, we get the object from session's get method. Here we pass a primary key in the get method and getting a persistent object.
3. When Delete an Entity Object
Here after getting persistent object from session of hibernate. When we are calling the delete method of the session object moves from persistent state to the transient state. If we calling the close method of the session then that object moves to the detached state. If once object move to the transient state it never become a persistent object. Now we look the states diagram of the entity object in the following.
When object in the session area then it is in Persistent State. When object before the session area then it is in Transient State. When object after the session area then it is in Detached State.
Detached to Persistent State:
Lets see in the following example how to an object moves from detached state to the persistent state again. HibernateTestDemo.java view plainprint?
1. 2. 3. 4. 5.
package com.sdnext.hibernate.tutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration;
6. 7. import com.sdnext.hibernate.tutorial.dto.UserDetails; 8. 9. public class HibernateTestDemo { 10. 11. /** 12. * @param args 13. */ 14. public static void main(String[] args) 15. { 16. UserDetails userDetails = new UserDetails(); 17. //Here 'userDetails' is in TRANSIENT state 18. 19. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil dSessionFactory(); 20. Session session = sessionFactory.openSession(); 21. session.beginTransaction(); 22. 23. userDetails = (UserDetails) session.get(UserDetails.class, 1); 24. //Here 'userDetails' is in PERSISTENT state 25. 26. session.save(userDetails); 27. session.getTransaction().commit(); 28. session.close(); 29. 30. session = sessionFactory.openSession(); 31. session.beginTransaction(); 32. 33. userDetails.setUserName("User Updated after session close"); 34. //Here 'userDetails' is in DETACHED state 35. 36. session.update(userDetails); 37. //Here 'userDetails' is again in PERSISTENT state 38. session.getTransaction().commit(); 39. session.close(); 40. } 41. }
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.ADDRESS as ADDRESS0_0_, userdetail0_.USER_NAME as USER3_0_0_ from User_Details userdetail0_ where userdetail0_.USER_ID=? Hibernate: select userdetail_.USER_ID, userdetail_.ADDRESS as ADDRESS0_, userdetail_.USER_NAME as USER3_0_ from User_Details userdetail_ where userdetail_.USER_ID=? Hibernate: update User_Details set ADDRESS=?, USER_NAME=? where USER_ID=?
Introducing HQL(Hibernate Query Language) and the Query Object : Chapter 26 Hibernate created a new language named Hibernate Query Language (HQL), the syntax is quite similar to database SQL language. The main difference between is HQL uses class name instead of table name, and property names instead of column name. Hibernate uses the following ways to retrieve objects from the database:
Hibernate Query Language (HQL)
Query By Criteria (QBC) and Query BY Example (QBE) using Criteria API
Native SQL queries The most preferred way is using the Hibernate Query Language (HQL), which is an easy-to-learn and powerful query language, designed as a minimal object-oriented extension to SQL. HQL has syntax and keywords/clauses very similar to SQL. It also supports many other SQL-like features, such as aggregate functions (for example: sum(), max()) and clauses such as group byand order by clause.
Why WE USE HQL? Although it is possible to use native SQL queries directly with a Hibernate-based persistence layer, it is more efficient to use HQL instead. The reasons of choosing HQL over the other two methods are given below. HQL allows representing SQL queries in object-oriented terms—by using objects and properties of objects. Instead of returning plain data, HQL queries return the query result(s) in the form of object(s)/tuples of object(s) that are ready to be accessed, operated upon, and manipulated programmatically. This approach does away with the routine task of creating and populating objects from scratch with the "resultset" retrieved from database queried. HQL fully supports polymorphic queries. That is, along with the object to be returned as a query result, all child objects (objects of subclasses) of the given object shall be returned.
HQL is easy to learn and implement, as its syntax and features are very similar to SQL.
HQL contains many advance features such as pagination, fetch join with dynamic profiling, and so forth, as compared to SQL. HQL facilitates writing database-type independent queries that are converted to the native SQL dialect of the underlying database at runtime. This approach helps tap the extra features the native SQL query provides, without using a non-standard native SQL query.
HQL Syntax>> As described earlier, most of HQL's syntax and features are very similar to SQL. An HQL query may consist of following elements:
Clauses
Aggregate functions
Subqueries Clauses in the HQL are: from
select
where
order by
group by Aggregate functions are: avg(...), sum(...), min(...), max(...)
count(*)
count(...), count(distinct ...), count(all...) Subqueries Subqueries are nothing but its a query within another query. Hibernate supports Subqueries if the underlying database supports it.
Table A: HQL Clauses with their description, syntax, and examples.
Claus Description e
Syntax
from The simplest form of an HQL query. Specifies the object whose instances are to be returned as the query result. Commonly used with the selectclause.
from object [as object_alias]* object_alias from UserDetails as simply means another name given to refer to user an object for convenience. Will return all instances of object UserDetails.
selec Specifies objects and properties to be returned t in the query result set. Used in conjunction with the fromclause.
select [object.]property
wher Specifies the conditions where condition that should be satisfied by e the instances returned as Here, condition is a combination of logical, the query result. Used relational operators i.e. =, >, AND, NOT etc. with select and/or from cl ause.
Example
select user.userName from UserDetails as user Will return all values of userName in all instances ofUserDetails. from UserDetails as user where user.userId > 2 Will return all instances of user in UserDetails whose correspondinguser.us erId values are greater than 2.
order Specifies the order (ascending/descending) in by which the properties of objects returned as query results should be listed. Used with the select and fromclause s.
order from UserDetails as by object0.property0[asc|desc][, object1.prop user order by userId erty0]... asc By default, order is ascending unless specified Will return a list of all instances of user in otherwise. ascending order of corresponding userId values.
grou Specifies the grouping group p by criteria using objects by object0.property0[,object1.property0]... properties, by which the list of objects returned as a query result should be grouped together. Used with the select and/or from cla use.
select userId from UserDetails as user group by user.userId Will return list of all userId instances from user grouped by corresponding values of user.
Select and Pagination in HQL : Chapter 27 Pagination of search results is a common requirement for any application. Out of performance reasons it is recommended to restrict the number of returned objects per query. In fact is a very common use case anyway that the user navigates from one page to an other. The way to define pagination is exactly the way you would define pagination in a plain HQL or Criteria query. Using the createQuery() method of a Session object that returns a Query object. First, instantiate the Session object using the openSession() method of SessionFactory. Then, invoke the createQuery() method on the resulting object. Query q = session.createQuery("..."); q.setFirstResult(start); q.setMaxResults(length); Student.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
package com.sdnext.hibernate.tutorial.dto; import java.io.Serializable; import import import import import import
javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.Table;
11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.
@Entity @Table(name="STUDENT") public class Student implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 8633415090390966715L; @Id @Column(name="ID") @GeneratedValue(strategy=GenerationType.AUTO) private int id; @Column(name="STUDENT_NAME") private String studentName; @Column(name="ROLL_NUMBER") private int rollNumber; @Column(name="COURSE") private String course; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public int getRollNumber() { return rollNumber; } public void setRollNumber(int rollNumber) { this.rollNumber = rollNumber; } public String getCourse() { return course; } public void setCourse(String course) { this.course = course; } public String toString() { return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
57. 58.
} }
hibernate.cfg.xml view plainprint?
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/hibernateDB2 6. root 7. root 8.
9. 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. update 26. 27. 28. 29. 30. 31.
HibernateTestDemo.java view plainprint?
1. package com.sdnext.hibernate.tutorial; 2. 3. import java.util.List; 4. 5. import org.hibernate.Query; 6. import org.hibernate.Session; 7. import org.hibernate.SessionFactory; 8. import org.hibernate.cfg.AnnotationConfiguration; 9. 10. import com.sdnext.hibernate.tutorial.dto.Student; 11. 12. public class HibernateTestDemo { 13. /** 14. * @param args 15. */ 16. public static void main(String[] args) 17. { 18. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil dSessionFactory(); 19. Session session = sessionFactory.openSession(); 20. session.beginTransaction(); 21. 22. String SQL_QUERY = "FROM Student student"; 23. Query query = session.createQuery(SQL_QUERY); 24. query.setFirstResult(1);//set first result start value 25. query.setMaxResults(5);//number of result to be display 26. 27. List students = query.list(); 28. for(Student student : students) 29. { 30. System.out.println(student); 31. } 32. session.getTransaction().commit();
33. 34. 35. 36.
session.close(); } }
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_, student0_.ROLL_NUMBER as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from STUDENT student0_ limit ?, ? ROLL Number: 2| Name: Sweety Rajput| Course: PGDCP ROLL Number: 3| Name: Adesh Rajput| Course: MA ROLL Number: 4| Name: DEV| Course: MA ROLL Number: 5| Name: RAJ| Course: BA ROLL Number: 6| Name: Pradeep| Course: BA
Parameter Binding and SQL Injection : Chapter 28 Parameter binding means is way to bind parameter with SQL to use in the hibernate for particular criteria.
SQL INJECTION: Injecting the value to the SQL statement. SQL injection refers to the act of someone inserting a MySQL statement to be run on your database without your knowledge. Injection usually occurs when you ask a user for input, like their name, and instead of a name they give you a MySQL statement that you will unknowingly run on your database. Normal: " SELECT * FROM student WHERE studentName= 'sweety'" Injection: "SELECT * FROM student WHERE studentName= '' +studentName
PARAMETER BINDING: A bind variable is a named placeholder (preceded by a colon) that is embedded in the query string in place of a literal. The actual value is substituted at runtime using the setParameter() method. Without parameter binding, you have to concatenate the parameter String like this (bad code) : view plainprint?
1. "'"; 2. 3.
String hql = "from Student student where student.studentName = '" + studentName+ Query query = session.createQuery(hql); List result = query.list();
Pass an unchecked value from user input to the database will raise security concern, because it can easy get hack by SQL injection. You have to avoid the above bad code and using parameter binding instead.
Hibernate parameter binding There are two ways to parameter binding : 1.
Named parameters binding
2.
Positional parameters binding.
1. Named Parameters Binding: This is the most common and user friendly way. It use colon followed by a parameter name (:example) to define a named parameter. See examples…
Example 1 – setParameter The setParameter is smart enough to discover the parameter data type for you. view plainprint?
1. 2. 3. 4.
String hql = "from Student student where student.rollNumber= :rollNumber"; Query query = session.createQuery(hql); query.setParameter("rollNumber", "3"); List result = query.list();
Example 2 – setString You can use setString to tell Hibernate this parameter date type is String. view plainprint?
1. 2. 3. 4.
String hql = "from Student student where student.studentName= :studentName"; Query query = session.createQuery(hql); query.setString("studentName", "Sweety Rajput"); List result = query.list();
Example 3 – setProperties This feature is great ! You can pass an object into the parameter binding. Hibernate will automatic check the object’s properties and match with the colon parameter. view plainprint?
1. 2. 3. 4. 5. 6.
Student student= new Student(); student.setCourse("MCA"); String hql = "from Student student where student.course= :course"; Query query = session.createQuery(hql); query .setProperties(student); List result = query.list();
2. Positional parameters It’s use question mark (?) to define a named parameter, and you have to set your parameter according to the position sequence. See example… view plainprint?
1. String hql = "from Student student where student.course= ? and student.studentNa me = ?"; 2. Query query = session.createQuery(hql); 3. query.setString(0, "MCA"); 4. query.setParameter(1, "Dinesh Rajput") 5. List result = query.list();
In Hibernate parameter binding, i would recommend always go for "Named parameters", as it’s more easy to maintain, and the compiled SQL statement can be reuse (if only bind parameters change) to increase the performance.
Named Queries in Hibernate : Chapter 29 Often times, developer like to put HQL string literals scatter all over the Java code, this method is hard to maintain and look ugly. Fortunately, Hibernate come out a technique called "named queries" , it lets developer to put all HQL into the XML mapping fileor via annotation.
Named Query is very useful concept in hibernate. It lets you separate queries from coding section of the application to themapping xml file(.hbm files). The query is given unique name for the entire application. The application can use the query by using the name of the query. This way the application is able to use the same query multiple times without writing the same query multiple times.
1. XML mapping file: student.hbm.xml Native SQL in mapping file: view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
HQL in mapping file view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
You can place a named query inside hibernate-mapping element, but do not put before the class element, Hibernate will prompt invalid mapping file, all your named queries have to put after the class element. hibernate.cfg.xml view plainprint?
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/hibernateDB2 6. root 7. root 8. 9.
10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. update 26. 27. 28. 29. 30. 31. 32.
HibernateTestDemo.java view plainprint?
1. package com.sdnext.hibernate.tutorial; 2. 3. import java.util.List; 4. 5. import org.hibernate.Query; 6. import org.hibernate.Session; 7. import org.hibernate.SessionFactory; 8. import org.hibernate.cfg.Configuration; 9. 10. import com.sdnext.hibernate.tutorial.dto.Student; 11. 12. public class HibernateTestDemo { 13. /** 14. * @param args 15. */ 16. public static void main(String[] args) 17. { 18. SessionFactory sessionFactory = new Configuration().configure().buildSessionFa ctory(); 19. Session session = sessionFactory.openSession(); 20. session.beginTransaction(); 21. 22. Query query = session.getNamedQuery("findStudentByRollNumber").setInteger("rol lNumber", 3); 23. 24. List students = query.list(); 25. for(Student student : students) 26. { 27. System.out.println(student); 28. } 29. session.getTransaction().commit(); 30. session.close(); 31. }
32. 33.
}
2. Annotation: HQL in annotation view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
@NamedQueries({ @NamedQuery( name = "findStudentByRollNumber", query = "from Student student where student.rollNumber = :rollNumber" ) }) @Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable { ...
Native SQL in annotation view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
@NamedNativeQueries({ @NamedNativeQuery( name = "findStudentByRollNumber", query = "select * from Student student where student.rollNumber = :rollNumbe" resultClass = Student.class ) }) @Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable { ...
In native SQL, you have to declare the ‘resultClass‘ to let Hibernate know what is the return type, failed to do it will caused the exception "org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported". Example: Student.java view plainprint?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
package com.sdnext.hibernate.tutorial.dto; import java.io.Serializable; import import import import import import import import
javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.NamedQueries; javax.persistence.NamedQuery; javax.persistence.Table;
@NamedQueries({ @NamedQuery( name = "findStudentByRollNumber", query = "from Student student where student.rollNumber = :rollNumber" )
19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64.
}) @Entity @Table(name="STUDENT") public class Student implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 8633415090390966715L; @Id @Column(name="ID") @GeneratedValue(strategy=GenerationType.AUTO) private int id; @Column(name="STUDENT_NAME") private String studentName; @Column(name="ROLL_NUMBER") private int rollNumber; @Column(name="COURSE") private String course; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public int getRollNumber() { return rollNumber; } public void setRollNumber(int rollNumber) { this.rollNumber = rollNumber; } public String getCourse() { return course; } public void setCourse(String course) { this.course = course; } public String toString() { return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
65. 66.
} }
hibernate.cfg.xml view plainprint?
1. 2. 3. 4. com.mysql.jdbc.Driver 5. jdbc:mysql://localhost:3306/hibernateDB2 6. root 7. root
8. 9. 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. update 26. 27. 28. 29. 30. 31.
HibernateTestDemo.java view plainprint?
1. package com.sdnext.hibernate.tutorial; 2. 3. import java.util.List; 4. 5. import org.hibernate.Query; 6. import org.hibernate.Session; 7. import org.hibernate.SessionFactory; 8. import org.hibernate.cfg.AnnotationConfiguration; 9. 10. import com.sdnext.hibernate.tutorial.dto.Student; 11. 12. public class HibernateTestDemo { 13. /** 14. * @param args 15. */ 16. public static void main(String[] args) 17. { 18. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil dSessionFactory(); 19. Session session = sessionFactory.openSession(); 20. session.beginTransaction(); 21. 22. Query query = session.getNamedQuery("findStudentByRollNumber").setInteger("rol lNumber", 3); 23. 24. List students = query.list(); 25. for(Student student : students) 26. { 27. System.out.println(student); 28. } 29. session.getTransaction().commit(); 30. session.close();
31. 32. 33.
} }
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_, student0_.ROLL_NUMBER as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from STUDENT student0_ where student0_.ROLL_NUMBER=? ROLL Number: 3| Name: Adesh Rajput| Course: MA
Criteria API in Hibernate : Chapter 30 There are three way to pulling data from the database in the Hibernate. 1. Using session methods(get() and load() methods) -limited control to accessing data 2. Using HQL - Slightly more control using where clause and other clauses but there are some problems here... is more complicated to maintain in case of bigger queries with lots of clauses. 3. Using Criteria API WHAT IS CRITERIA API? The API (Application Programming Interface) of Hibernate Criteria provides an elegant way of building dynamic query on the persistence database. The hibernate criteria API is very Simplified API for fetching data from Criterion objects. The criteria API is an alternative of HQL (Hibernate Query Language) queries. It is more powerful and flexible for writing tricky criteria functions and dynamic queries 1. Using Criteria API to create criteria: view plainprint?
1.
Criteria criteria = session.createCriteria(Student.class);
2. The Criteria API supports all the comparision operators such as =, , >=,= 10. 1 11. 12. 13. org.hibernate.dialect.MySQLDialect 14. 15. 16. thread 17. 18. 19. org.hibernate.cache.NoCacheProvider 20. 21. 22. true 23. 24. 25. update 26. 27.
28. 29. 30. 31.
HibernateTestDemo.java view plainprint?
1. package com.sdnext.hibernate.tutorial; 2. 3. import java.util.List; 4. 5. import org.hibernate.Criteria; 6. import org.hibernate.Session; 7. import org.hibernate.SessionFactory; 8. import org.hibernate.cfg.AnnotationConfiguration; 9. import org.hibernate.criterion.Restrictions; 10. 11. import com.sdnext.hibernate.tutorial.dto.Student; 12. 13. 14. public class HibernateTestDemo { 15. 16. /** 17. * @param args 18. */ 19. public static void main(String[] args) 20. { 21. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil dSessionFactory(); 22. Session session = sessionFactory.openSession(); 23. session.beginTransaction(); 24. 25. Criteria criteria = session.createCriteria(Student.class); 26. criteria.add(Restrictions.eq("studentName", "Dinesh Rajput")); 27. 28. List students = criteria.list(); 29. 30. for(Student student : students) 31. { 32. System.out.println(student); 33. } 34. session.getTransaction().commit(); 35. session.close(); 36. } 37. 38. } 39.
Output: log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize the log4j system properly. Hibernate: select this_.ID as ID0_0_, this_.COURSE as COURSE0_0_, this_.ROLL_NUMBER as ROLL3_0_0_, this_.STUDENT_NAME as STUDENT4_0_0_ from STUDENT this_ where this_.STUDENT_NAME=? ROLL Number: 1| Name: Dinesh Rajput| Course: MCA
In the Next Chapter we will discuss more about the Criteria Query with Restriction.
Restrictions in Hibernate : Chapter 31 In this chapter, you will see the use of Restrictions class in java. It is used to restrict the retrieval of data from database. Syntax: view plainprint?
1. 2.
Criteria criteria = session.createCriteria(Model.class); criteria.add(Restrictions.eq(propertyName, propertyValue));
Criteria restrictions query The Restrictions class provide many methods to do the comparison operation. Restrictions.eq This is used to apply an "equal" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber = 3;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.eq("rollNumber", 3)); List list = criteria.list();
Restrictions.lt This is used to apply a "less than" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber < 3;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.lt("rollNumber", 3)); List list = criteria.list();
Restrictions.gt This is used to apply a "greater than" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber > 3;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.gt("rollNumber", 3)); List list = criteria.list();
Restrictions.le This is used to apply a "less than or equal" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber > view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.le("rollNumber", 3)); List list = criteria.list();
Restrictions.ge This is used to apply a "greater than or equal" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber >= 3;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.ge("rollNumber", 3)); List list = criteria.list();
Restrictions.ne This is used to apply a "not equal" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber 3;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.ne("rollNumber", 3)); List list = criteria.list();
Restrictions.in This is used to apply an "in" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber IN (3,5,7);
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.in("rollNumber", new Integer[]{3,5,7})); List list = criteria.list();
Restrictions.or This returns the disjunction of two expressions. Simple SQL query >>
view plainprint?
1.
SELECT * FROM student WHERE rollNumber > 3 OR course='MA';
Above query in Criteria API >> view plainprint?
1. Criteria criteria = session.createCriteria(Student.class); 2. criteria.add(Restrictions.or(Restrictions.gt("rollNumber", 3), Restrictions.eq(" course", "MA")); 3. List list = criteria.list();
Restrictions.not This returns the negation of an expression. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber NOT IN (3,5,7);
Above query in Criteria API >> view plainprint?
1. 2. ))); 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.not(Restrictions.in("rollNumber", new Integer[]{3,5,7} List list = criteria.list();
Restrictions.like This is used to apply a "like" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE studentName LIKE %RAJPUT%;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.like("studentName", "%RAJPUT%")); List list = criteria.list();
Restrictions.isNull This is used to apply an "is null" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE studentName IS NULL;
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.isNull("studentName")); List list = criteria.list();
Restrictions.isNotNull This is used to apply an "is not null" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE studentName IS NOT NULL;
Above query in Criteria API >> view plainprint?
1. 2.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.isNotNull("studentName"));
3.
List list = criteria.list();
Restriction.between This is used to apply a "between" constraint to the named property. Simple SQL query >> view plainprint?
1.
SELECT * FROM student WHERE rollNumber BETWEEN (3,7);
Above query in Criteria API >> view plainprint?
1. 2. 3.
Criteria criteria = session.createCriteria(Student.class); criteria.add(Restrictions.between("rollNumber", 3, 7)); List list = criteria.list();
Restriction.allEq This is used to apply an "equals" constraint to each property in the key set of a Map. Simple SQL query >> view plainprint?
1.
SELECT * FROM user WHERE userName = +userName AND userPassword = +userPassword;
Above query in Criteria API >> view plainprint?
1. 2. 3. 4. 5. 6.
Map map = new HashMap(); map.put("username", username); map.put("userPassword", userPassword); Criteria criteria = session.createCriteria(User.class); criteria.add(Restrictions.allEq(map)); List list = criteria.uniqueResult();
Cacheing in Hibernate: First Level and Second Level Cache in Hibernate : Chapter 32 In earlier we said that hibernate much more than an ORM tool i.e. Hibernate provide the lots of other features. In which Cache is very important feature one of them. Hibernate is actually a very powerful, consistent, and reliable database mapping tool. Mapping between objects in Java to relational databases has many facets that you must be aware of. Hibernate does a particularly good job of making the process simple to start, and providing the facilities to allow it to scale well and meet exceedingly complex mapping demands. Caching is all about application performance optimization and it sits between your application and the database to avoid the number of database hits as many as possible to give a better performance for performance critical applications. Caching is important to Hibernate as well which utilizes a multilevel caching schemes as explained below:
One of the primary concerns of mappings between a database and our Java application is performance. This is the common concern of the all guys who working with hibernate and spent the more time in ORM tools for performance-enhancing changes to particular queries and retrievals. Today I want to discuss about some facets of the Hibernate infrastructure that are implemented to handle certain performance concerns 1. The first-level cache - Session (Earlier hibernate already provide this level of cache) 2. The second-level cache -Session-factory-level cache 3. and the query cache. The first-level cache: The first level cache type is the session cache. The session cache caches object within the current session but this is not enough for long level i.e. session factory scope. The second-level cache: The second-level cache is called 'second-level' because there is already a cache operating for you in Hibernate for the duration you have a session open. A Hibernate Session is a transaction-level cache of persistent data. It is possible to configure a SessionFactory-level cache on a class-by-class and collection-by-collection basis. second-level cache -- Across sessions in an Application -- Across applications (different applications on same servers with same database) -- Across clusters (different applications on different servers with same database)
NOTE: Be careful Caches are never aware of changes made to the persistent store by another application i.e. suppose one application deploy one server with using hibernate and get the data from database and put to the cache for further using purpose but another application deployed another server which does not using any ORM tool so it does mot know about Cache and direct interacting with database and may be update data of database. Now data in Cache is invalid.
Hibernate uses first-level cache by default and you have nothing to do to use first-level cache. Let's go straight to the optional second-level cache. Not all classes benefit from caching, so it's important to be able to disable the second-level cache. The 'second-level' cache exists as long as the session factory is alive. The second-level cache holds on to the 'data' for all properties and associations (and collections if requested) for individual entities that are marked to be cached. In hibernate configuration file (hibernate.cfg.xml) we wrote the following line. For Disabling the second level of cache we have to made following change to hibernate configuration file. view plainprint?
1. 2. rty>
org.hibernate.cache.NoCacheProvider
View more...
Comments