Hibernate Basics
Agenda
- Understanding Hibernate
- Setup
- Hibernate xml configurations
- hbm2ddl options
- @Id and @Entity annotations
- CRUD
- Transient, Persistent and Detached states
- Name Annotations
- Generating Primary Key
- Embedded types
- Saving Collections
- Configuring Collections and Adding Keys
- Generate Id for Join Tables
Agenda (Cont.)
- Proxy Object, Eager and Lazy Fetching
- One to One Mapping
- One to Many Mapping
- Many to Many Mapping
- Cascading
What is Hibernate?
- An ORM tool
- Used in the data layer of applications
- Implements JPA
The Problem solved by hibernate
User Class |
---|
Id |
Name |
Address |
Phone |
Date of Birth |
Id | Name | Address | Phone | Date of Birth |
---|---|---|---|---|
The Problem solved by hibernate (Cont.)
- Mapping member variables to column
- Mapping relationships
- Handling data types
- Managing changes to object state
Set up with gradle
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile('org.hibernate:hibernate-core:5.2.6.Final')
compile ('mysql:mysql-connector-java:5.1.6')
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--Database connection settings -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/poc</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"/>
<!--JDBC connection pool-->
<property name="connection.pool_size">10</property>
<!-- SQL Dialect-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--echo all executed SQL-->
<property name="show_sql">true</property>
<!--drop or re-create database schema at startup-->
<property name="hbm2ddl.auto">create</property>
<!--Annotated entity class-->
<mapping class="com.hibernate.demo.Person"/>
</session-factory>
</hibernate-configuration>
hibernate.cfg.xml
hbm2ddl configurations
- update: update the schema.
- create: creates the schema, destroying previous data.
- create-drop: drop the schema when the SessionFactory is closed explicitly, typically when the application is stopped.
- none: Do not do anything.
Special note about update for hbm2ddl auto
-
update won't modify existing table column definitions.
-
update will add a db column that doesn't already exist.
-
update will not delete a db column that is removed/no longer in your entity.
-
update will not modify a db column that has already been created.
@Id and @Entity
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Person {
@Id
Integer id;
String name;
Integer age;
}
- @Entity : Marks the class as entity.
- @Id : Specifies primary key for the entity.
CRUD (Create)
- Create a session factory
- Create a session from session factory
- Use the session to save model objects
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
CRUD (Read)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
session.getTransaction().commit();
session.close();
System.out.println(person);
session.close();
sessionFactory.close();
}
}
CRUD (Update)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
person.setName("Updated Name");
session.update(person);
session.getTransaction().commit();
session.close();
System.out.println(person);
session.close();
sessionFactory.close();
}
}
CRUD (Delete)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
session.delete(person);
session.getTransaction().commit();
session.close();
System.out.println(person);
session.close();
sessionFactory.close();
}
}
Exercise 1
- Create a class Author with instance variables firstName, lastName and age.
- Perform CRUD operation for Author class.
- Use hbm2ddl create to introduce Date of Birth for Author.
- Use hbm2dll update to insert at least 4 records for Author.
- Perform hbm2dll create-drop by closing session factory.
Transient, Persistent and Detached states
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
//Transient state
person.setName("Hibernate");
person.setAge(23);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
//Persistent state
session.save(person);
person.setName("Updated");
session.getTransaction().commit();
session.close();
sessionFactory.close();
//Detached state
person.setName("Updated in detached");
}
}
Name Annotations
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity(name = "Employee")
public class Person {
@Id
Integer id;
@Column(name = "First_Name")
String name;
Integer age;
}
- Name property can be used with @Entity and @Column annotation to specify the name of table and column.
- @Id and @Column annotations can be used with getters also.
More Annotations
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "Employee")
public class Person {
@Id
Integer id;
@Column(name = "First_Name")
String name;
@Transient
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
}
- @Table annotation is used to store specify the name of the table for entity.
- @Transient is used to ignore the field of an entity while persisting it into a database.
- @Temporal annotation is used with Date types to specify what should be saved i.e DATE, TIME or TIMESTAMP
Automatically generate primary key value
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
}
- @GenerateValue annotation can be used to generate id for objects while persistence.
- AUTO: Hibernate selects the generation strategy based on the used dialect
- IDENTITY: Hibernate relies on an auto-incremented database column to generate the primary key,
- SEQUENCE: Hibernate requests the primary key value from a database sequence,
- TABLE: Hibernate uses a database table to simulate a sequence.
Id Generation Stratergies
Exercise 2
- Test Transient, Persistent and Detached state for Author Object.
- Provide name Write to Author Table
- Rename all the fields using column annotation.
- Mark lastName as @Transient.
- Use @Temporal for date of birth of Author.
- Generate Id for Author Using IDENTITY and TABLE starategy.
Embedded Type
import javax.persistence.*;
@Entity
public class Person{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
String name;
Integer age;
@Embedded
Address address;
}
For embedded object we can use @Embedded annotation for the Reference type instance variable
import javax.persistence.Embeddable;
@Embeddable
public class Address {
String city;
String country;
}
Optionally we can also place @Embeddable on the class of the reference type instance variable
Embedded type (Cont.)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(23);
Address address=new Address();
address.setCity("Delhi");
address.setCountry("India");
person.setAddress(address);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.getTransaction().commit();
session.close();
}
}
Overriding attributes
import javax.persistence.*;
@Entity
public class Person{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
String name;
Integer age;
@Embedded
Address address;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name = "CURRENT_CITY")),
@AttributeOverride(name = "country", column = @Column(name = "CURRENT_COUNTRY"))
})
Address currentAddress;
}
import javax.persistence.Column;
public class Address {
@Column(name = "HOME_CITY")
String city;
@Column(name = "HOME_COUNTRY")
String country;
}
Exercise 3
- Create a class Address for Author with instance variables streetNumber, location, State.
- Use @Column to give column name to the instance variables of Address class.
- Create instance variable of Address class inside Author class and save it as embedded object.
- Now introduce one more Address type as currentAddress and Override attributes of Address class.
Saving Collections
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
@ElementCollection
Set<String> hobbies=new HashSet<String>();
}
- @ElementCollection annotation is used to persist collections in Hibernate entities
Configuring Collections and Adding Keys
@JoinTable annotatation is used to specify the name of the table and column which will be used to join collection table with the parent table.
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
@JoinTable(name = "employee_hobbies",
joinColumns = @JoinColumn(name = "CUSTOM_JOIN_ID"))
@ElementCollection
Set<String> hobbies=new HashSet<String>();
}
Generate Id for Join Table
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
@JoinTable(name = "employee_hobbies",
joinColumns = @JoinColumn(name = "CUSTOM_JOIN_ID"))
@ElementCollection
@GenericGenerator(name = "sequence-gen",strategy = "sequence")
@CollectionId(columns = {@Column(name = "hobbies_id")},
generator = "sequence-gen",type = @Type(type = "long"))
Collection<String> hobbies=new HashSet<String>();
}
@CollectionId and @Generic Generator annotaions are use to Generate Id of a Join Table in the following way:
import javax.persistence.*;
import java.util.*;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
@JoinTable(name = "employee_hobbies",
joinColumns = @JoinColumn(name = "CUSTOM_JOIN_ID"))
@ElementCollection(fetch = FetchType.EAGER)
Collection<String> hobbies=new ArrayList<String>();
}
Proxy Objects and Eager and Fetch Types
By Default Hibernate creates a proxy object and fills first level instance variables. To fetch Collection instance variables with object we need to set FetchType.Eager in @ElementCollection.
Exercise 4
- Introduce a List of subjects for author.
- Persist 3 subjects for each author.
- Provide name to the JointTable and JoinColumn.
- Generate Id For Join Table.
- Experiment with Proxy and Eager Fetching.
One to One mapping
import javax.persistence.*;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToOne
@JoinColumn(name = "Vehicle_join_column")
Vehicle vehicle;
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
}
One to One mapping (Cont.)
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
person.setVehicle(vehicle);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.getTransaction().commit();
session.close();
One to Many (Unidirectional)
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany
@JoinTable(joinColumns = @JoinColumn(name="USER_ID")
,inverseJoinColumns = @JoinColumn(name = "VEHICAL_ID"))
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
}
One to Many (Unidirectional) Cont.
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
Vehicle vehicle2=new Vehicle();
vehicle2.setVehicleName("Bike");
person.getVehicle().add(vehicle);
person.getVehicle().add(vehicle2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.save(vehicle2);
session.getTransaction().commit();
session.close();
One to Many (Bidirectional)
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany
@JoinTable(joinColumns = @JoinColumn(name="USER_ID")
,inverseJoinColumns = @JoinColumn(name = "VEHICAL_ID"))
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToOne
Person person;
}
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
vehicle.setPerson(person);
Vehicle vehicle2=new Vehicle();
vehicle2.setPerson(person);
vehicle2.setVehicleName("Bike");
person.getVehicle().add(vehicle);
person.getVehicle().add(vehicle2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.save(vehicle2);
session.getTransaction().commit();
session.close();
One to Many (Bidirectional) Cont.
One to Many without additional table
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany(mappedBy = "person")
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToOne
Person person;
}
Many to Many
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@ManyToMany
List<Vehicle> vehicle= new ArrayList<Vehicle>();
}
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToMany(mappedBy = "vehicle")
List<Person> personList = new ArrayList<Person>();
}
Cascade Type
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Person{
@Id @GeneratedValue(strategy = GenerationType.TABLE)
Integer id;
String name;
Integer age;
@OneToMany(cascade = CascadeType.PERSIST)
List<Vehicle> listOfVehicles=new ArrayList<Vehicle>();
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.TABLE)
Integer vehicleId;
String vehicleName;
}
Cascade Type (Cont.)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(23);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
person.getListOfVehicles().add(vehicle);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.persist(person);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
Exercise 5
- Create an Entity book with an instance variable bookName.
- Implement One to One mapping between Author and Book.
- Implement One to Many Mapping between Author and Book(Unidirectional, BiDirectional and without additional table ) and implement cascade save.
- Implement Many to Many Mapping between Author and Book.
Hibernate Basics
By Pulkit Pushkarna
Hibernate Basics
- 1,409