0% found this document useful (0 votes)
62 views

Hibernate: Thanh N Nguyen

Hibernate is a popular Java ORM tool that maps Java objects to database tables to reduce boilerplate code when performing CRUD operations through JDBC, it provides benefits like eliminating resource leaks, supporting object relationships and queries through HQL, and its use is configured through annotations on POJO classes and by defining a SessionFactory bean that connects to the database.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
62 views

Hibernate: Thanh N Nguyen

Hibernate is a popular Java ORM tool that maps Java objects to database tables to reduce boilerplate code when performing CRUD operations through JDBC, it provides benefits like eliminating resource leaks, supporting object relationships and queries through HQL, and its use is configured through annotations on POJO classes and by defining a SessionFactory bean that connects to the database.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

Hibernate

Thanh N Nguyen
What is Hibernate?
● Hibernate is one of the most widely used Java ORM tool.
● Most of the applications use relational databases to store application
information
● At the low level, JDBC API is used for connecting to databases and perform
CRUD operations.

RMIT University
Why Hibernate?
● In JDBC code, there is so much of boilerplate code
● There are chances of resource leak and data inconsistency
● All the work needs to be done by the developer.
● Object-relational mapping or ORM is the programming technique to map
application domain model objects to the relational database tables.
● Hibernate is java based ORM tool that provides framework for mapping
application domain objects to the relational database tables and vice versa.

RMIT University
Benefits of Hibernate
● Hibernate supports mapping of java classes to database tables and vice versa. It
provides features to perform CRUD operations across all the major relational
databases.
● Hibernate eliminates all the boiler-plate code that comes with JDBC and takes care of
managing resources, so we can focus on business use cases rather than making sure
that database operations are not causing resource leaks.
● Hibernate supports transaction management and make sure there is no inconsistent
data present in the system.
● Since we use XML, property files or annotations for mapping java classes to database
tables, it provides an abstraction layer between application and database.

RMIT University
Benefits of Hibernate
● Hibernate helps us in mapping joins, collections, inheritance objects and we can easily
visualize how our model classes are representing database tables.
● Hibernate provides a powerful query language (HQL) that is similar to SQL. However,
HQL is fully object-oriented and understands concepts like inheritance, polymorphism
and association.
● Hibernate also offers integration with some external modules. For example Hibernate
Validator is the reference implementation of Bean Validation (JSR 303).
● Hibernate is an open source project from Red Hat Community and used worldwide. This
makes it a better choice than others because learning curve is small and there are tons
of online documentations and help is easily available in forums.
● Hibernate is easy to integrate with other Java EE frameworks, it’s so popular that Spring
Framework provides built-in support for integrating hibernate with Spring applications.

RMIT University
Hibernate
Architecture
Hibernate Architecture

RMIT University
Three components of an Hibernate app

● Annotated POJO classes


● A sessionFactory bean!!! Most important object (bean)
● A transactionManager bean!!! (don’t touch it)

RMIT University
Hibernate vs JPA (Java
Persistence API)
● JPA is the dance, Hibernate is the dancer.
● JPA is the interface while Hibernate is the implementation.
● Traditionally there have been multiple Java ORM solutions:
• Hibernate
• TopLink
• JDO

Hibernate offers features that are not yet supported by JPA

RMIT University
POJO classes
● a plain old Java object (POJO) is an ordinary Java object, not bound by any
special restriction and not requiring any class path (Entity)
● POJO should not have to
○ Extends a class
public class Foo extends javax.servlet.http.HttpServlet { …
○ Implements an interface
public class Bar implements javax.ejb.EntityBean { ...

RMIT University
Annotated POJO classes
● There are different
annotations
@Entity
@Entity, @Table, @Id,
public class Person {
@Column,
@Id
@GeneratedValue
@Column
● These annotations are @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
provided by JPA
NOT by Hibernate @Column
private String name;
}

RMIT University
@Entity
● Marks this class as an entity bean, so it must have a no-argument constructor
that is visible with at least protected scope.
@Entity
public class Person {

@Id
@Column
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Column
private String name;
}

RMIT University
@Table
The @Table annotation allows you to specify the details of the table that will be
used to persist the entity in the database.

The @Table annotation provides four attributes, allowing you to override the
name of the table, its catalogue, and its schema, and enforce unique constraints
on columns in the table

RMIT University
@Id and @GeneratedValue
● Each entity bean will have a primary key, which you annotate on the class with
the @Id annotation.
● The primary key can be a single field or a combination of multiple fields
depending on your table structure.
● By default, the @Id annotation will automatically determine the most
appropriate primary key generation strategy to be used
● You can override this by applying the @GeneratedValue annotation, which
takes two parameters strategy and generator

RMIT University
@Column
● The @Column annotation is used to specify the details of the column to which
a field or property will be mapped. You can use column annotation with the
following most commonly used attributes −
○ name attribute permits the name of the column to be explicitly specified.
○ length attribute permits the size of the column used to map a value
particularly for a String value.
○ nullable attribute permits the column to be marked NOT NULL when the
schema is generated.
○ unique attribute permits the column to be marked as containing only
unique values.

RMIT University
SessionFactory
● Hibernate can work well without Spring.
● But Spring makes Hibernate become much easier to use, i.e. Spring wrap all
boilerplate codes into some simple interfaces.
● The most important class in Spring Hibernate is SessionFactory. It provides
a single point of contact that helps to create, add, update, delete, and query
data from any databases.

RMIT University
How to create a sessionFactory
● To create a sessionFactory bean we need to provide 3 sets of information:
● DataSource: What database and where it is (url), username and password
to connect?
● HibernateProperties: To tell Hibernate whether we want it create table for us or
display sql statement that it uses when it performs some tasks.
● PackageToScan: The name of package where entity classes are placed.
Entity classes are classes that directly map to database table.

RMIT University
dataSource
● sessionFactory needs a dataSource, i.e. database info

DriverManagerDataSource dataSource = new DriverManagerDataSource();

//To use postgresql


dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/ead");
dataSource.setUsername("postgres");
dataSource.setPassword("rmit");

RMIT University
hibernateProperties
● Additional info for Hibernate

Properties properties = new Properties();


properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.show_sql", true);
properties.put("hibernate.hbm2ddl.auto", "update");

RMIT University
packageToScan
● The package that contains annotated POJO

sessionFactoryBean.setPackagesToScan("rmit.entity");

RMIT University
SessionFactory in Action
@Bean
public LocalSessionFactoryBean sessionFactory(){

Properties properties = new Properties();


properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.show_sql", true);
properties.put("hibernate.hbm2ddl.auto", "update");

DriverManagerDataSource dataSource = new DriverManagerDataSource();

//To use postgresql


dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/hello");
dataSource.setUsername("postgres");
dataSource.setPassword("rmit");

LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();


sessionFactoryBean.setDataSource(dataSource);

sessionFactoryBean.setHibernateProperties(properties);
sessionFactoryBean.setPackagesToScan("rmit.entity");

RMIT University return sessionFactoryBean;


}
Hibernate relationship
Association between entities (relationship between tables) is a complex topic. In database, there are 3 types of relationships:
- One - One:
A person will have one address at a time. Often, we put the primary key of address to person table. That’s enough.
- Many - Many:
There are many examples of this relationship.
A student studies many courses. A course is studied by many students.
An order has many products and a product can appear in many orders.

We have to generate a 3rd table to store the primary keys of both sides.
This approach is however very limited. What if we also want to record mark of each student in a course? What if in an order, customers
buy more than one item.

To address this problem, it is better to convert 1 many - many to 2 many - one relationship.
Student - Course → Student - Course Registration and Course - Course Registration.

For example:
course (id, name)
student (id, name)
course_registration(id, courseId, studentId, mark)

RMIT University
Hibernate relationship cont
- One - Many:
This may be the most common one.
A father has many children. But each child has only one father.
A post has many comments. But each comment belongs to only one post.
An order has many order details. But each detail belongs to only one order.

We address this relationship by putting the primary key of the One end to the Many end.

Learn the following example by heart !!!!

RMIT University
How do we do 2 one-many relationships?
@Entity @Entity
@Entity
public class Student { public class CourseRegistration {
public class Course {
@Id @Id
@Id
@Column @Column
@Column
@GeneratedValue(strategy = @GeneratedValue(strategy =
@GeneratedValue(strategy =
GenerationType.IDENTITY) GenerationType.IDENTITY)
GenerationType.IDENTITY)
private int id; private int id;
private int id;

@Column @ManyToOne
@Column
private String name; private Course course;
private String name;

@OneToMany(mappedBy = "student") @ManyToOne


@OneToMany(mappedBy = "course")
private List<CourseRegistration> private Student student;
private List<CourseRegistration>
courseRegistrations; }
courseRegistrations;
}
}

RMIT University
Hibernate Query
● Hibernate offers 3 methods of query:
○ Criteria
○ HQL Query and HQL Query with params
○ SQL Query

RMIT University
Criteria
public List<Person> getAllPersons(){
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class);
return criteria.list();
}

public List<Person> getPersonByName(String name){


Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Person.class);
criteria.add(Restrictions.like("name",name, MatchMode.ANYWHERE));
return criteria.list();
}

RMIT University
HQL
public List<Person> getPersonByName2(String name){
Query query = sessionFactory.getCurrentSession().createQuery("from Person where name like
:name");
query.setString("name", "%"+name+"%");
return query.list();
}

RMIT University
SQL
public List<Person> getPersonByName3(String name){
SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery("select * from newperson
where name like ‘“+name+”’");
return query.list();
}

● Dangerous as it exposes risk of SQL Injection

RMIT University
Hibernate cascading
● Cascading refers to an action made to object (add, update, delete) in one class that can trigger
action to other class.
● For example, a student has many courseRegistrations, what happen if we delete that student?
Whether all courseRegistration objects linked to that student be removed? This is DELETE cascade.
● Another example is if we save a student that has two courseRegistrations, will these
courseRegistrations be saved to database as well? This is ADD cascade.
● To apply cascade we apply @Cascade to the collection property of the One side, i.e. Student class
in this case:

@OneToMany(mappedBy = "student")
@Cascade(CascadeType.SAVE_UPDATE)
private List<Registration> courseRegistrations;

RMIT University
Hibernate cascading cont
● For all cascade types we use CascadeType.All.
● For delete cascade we use CascadeType.DELETE
● For add/update we use CascadeType.SAVE_UPDATE

Registration registration1 = new Registration();


Hibernate: insert into Registration (course_id, student_id)
Registration registration2 = new Registration();
values (?, ?)
Hibernate: insert into Registration (course_id, student_id)
List<Registration> list = new ArrayList<Registration>();
values (?, ?)
list.add(registration1);
list.add(registration2);

Hibernate: delete from Registration where id=?


course.setCourseRegistrations(list);
Hibernate: delete from Registration where id=?
Hibernate: delete from Course where id=?
courseService.addCourse(course);

courseService.deleteCourse(course);

RMIT University
Optional topics
All discussions to fetchType and fetchMode below are
optional

RMIT University
Fetch Type vs Fetch Mode
● Is a complicated topic related to Hibernate performance optimization
● PS. All optimization activities suppose to be complex

RMIT University
Fetch Type
● LAZY = fetch when needed;
● EAGER = fetch immediately
● EAGER loading of collections means that they are fetched fully at the time their parent
is fetched. So if you have Course and it has List<Student>, all the students are fetched
from the database at the time the Course is fetched.
● LAZY means that the contents of the List are fetched only when you try to access them.
For example, by calling course.getStudents().iterator(). Calling any access method on
the List will initiate a call to the database to retrieve the elements. This is implemented
by creating a Proxy around the List (or Set). So for your lazy collections, the concrete
types are not ArrayList and HashSet, but PersistentSet and PersistentList (or
PersistentBag)

RMIT University
Fetch type cont
● Default fetch type in Hibernate:
● ManyToOne: EAGER
● OneToMany: LAZY
● We should not override the fetch type LAZY in OneToMany

RMIT University
Where to put Fetch Type
After @OneToMany

@OneToMany(mappedBy = "question", fetch = FetchType.EAGER)


@Cascade(CascadeType.SAVE_UPDATE)
private Set<Answer> answers;

RMIT University
Fetch Mode vs Fetch Type
FetchMode : It defines how hibernate (using which strategy, e.g. Join, SubQuery etc) will fetch data from
database.
FetchType : It defines whether hibernate will fetch the data or not.

4 fetch modes:

1. fetch-“join” = Disable the lazy loading, always load all the collections and entities.
2. fetch-“select” (default) = Lazy load all the collections and entities.
3. batch-size=”N” = Fetching up to ‘N’ collections or entities, *Not record*.
4. fetch-“subselect” = Group its collection into a sub select statement.

RMIT University
When to use?
FetchMode SELECT
Use this when you want a quick response time when working on a single entity. SELECT creates small queries and only fetches the data
which is absolutely needed. The use-case in our example could be an application to which displays one Customer with its Invoices.

BatchSize
BatchSize is useful when working with a fixed set of data. When you have a batch processing 10 Customers at a time a BatchSize of 10
will drastically reduced the number of queries needed.If the BatchSize is not set too high the query will most likely return a manageable
amount of data in a reasonable time.

FetchMode JOIN
As indicated you’ll have to worry about duplicated results. On the other hand JOIN creates the least amount of queries. In a high latency
environment a single JOIN could be considerable faster then multiple SELECTS. Keep in mind that joining too much data could put a
strain on the database.

FetchMode SUBSELECT
If you’ve got an entity of which you know that there aren’t that many of them, and almost all of them are in the session, then
SUBSELECT should be a good choice. Just keep in mind that all collections are fetched, even if the parent is not in the session. A
SUBSELECT when having a single Customer in session while there are 1000+ in the database will be wasteful.

RMIT University
N+1 problem
● Happen when use
FetchType: LAZY
FetchMode: SELECT
● Each query for parent object will trigger a query for a child collection
● Solution:
○ Use FetchMode: JOIN
○ Or Use FetchMode: SUBQUERY
○ Or Use FetchMode: SELECT with BatchSize

RMIT University
Hibernate FetchMode in RESTful
SpringMVC
● Quite complicated
● SELECT and BatchSize might be an appropriate strategy

RMIT University
FetchMode
● The Hibernate Relations Works with different Fetch Strategies..!!
● Hibernate provides 4 strategies for retrieving data:

SELECT

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL) @Column(name="id")


@Fetch(FetchMode.SELECT)

In this Method there are Multiple SQLs fired. This first one is fired for retrieving all the records in the Parent table. The
remaining are fired for retrieving records for each Parent Record. This is basically the N+1 problem. The first query
retrieves N records from database, in this case N Parent records. For each Parent a new query retrieves Child. Therefore
for N Parent, N queries retrieve information from Child table.

RMIT University
FetchMode more...
JOIN

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL) @Column(name="id") @Fetch(FetchMode.JOIN)

This is similar to the SELECT fetch strategy except that fact that all database retrieval take place upfront in JOIN fetch
unlike in SELECT where it happens on a need basis. This can become an important performance consideration.
SUBSELECT

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL) @Column(name="id")


@Fetch(FetchMode.SUBSELECT)

Two SQLs are fired. One to retrieve all Parent and the second uses a SUBSELECT query in the WHERE clause to
retrieve all child that has matching parent ids.
BATCH

@OneToMany(mappedBy="tableName", cascade=CascadeType.ALL) @Column(name="id") @@BatchSize(size=2)

The batch size maps to the number of Parent whose child are retrieved. So we can specify the number of records to be
fetched at a time.But Multiple queries will be executed.!

RMIT University

You might also like